commit 506e23bf32b304256fcf15a3d1c0e09c6b82207d Author: Ondrej Novak Date: Fri Jan 24 18:27:22 2025 +0100 github publish diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb384a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.user +*.old +*.XML +.svn +_UpgradeReport_Files +/Bin +/Debug \ No newline at end of file diff --git a/.vs/Skeldal/v17/.suo b/.vs/Skeldal/v17/.suo new file mode 100644 index 0000000..369497b Binary files /dev/null and b/.vs/Skeldal/v17/.suo differ diff --git a/3DTEST/TEXTURAA.ASM b/3DTEST/TEXTURAA.ASM new file mode 100644 index 0000000..58da83a --- /dev/null +++ b/3DTEST/TEXTURAA.ASM @@ -0,0 +1,64 @@ +.model small +.386 + +DGROUP group _DATA + +extrn _start_poss:word +extrn _end_poss:word +extrn _scr_max_x:dword +extrn _scr_next_line:dword + +_TEXT segment byte public 'CODE' use32 + assume CS:_TEXT + assume DS:DGROUP + +public draw_flat_triangle_ +draw_flat_triangle_: +dft_lp2:mov ebx,edi + movsx edx,_start_poss[esi*2] + lea edi,[ebx+edx*2] + cmp dx,_end_poss[esi*2] + jz dft_skpa + jl dft_dirr + std + cmp edx,0 + js dft_skpa + cmp edx,_scr_max_x + jbe dft_drr1 + mov edi,_scr_max_x + lea edi,[ebx+edi*2] + jmp dft_drr1 +dft_dirr:cld + cmp edx,_scr_max_x + jg dft_skpa + cmp edx,0 + jns dft_drr1 + mov edi,ebx +dft_drr1:movsx edx,_end_poss[esi*2] + cmp edx,0 + jns dft_dc1 + xor edx,edx + jmp dft_dc2 +dft_dc1:cmp edx,_scr_max_x + jna dft_dc2 + mov edx,_scr_max_x +dft_dc2:shl edx,1 + add edx,ebx +dft_lp1: stosw + cmp edi,edx + jnz dft_lp1 +dft_skpa: + stosw + mov edi,_scr_next_line + lea edi,[ebx+edi] + inc esi + dec ecx + jnz dft_lp2 + cld + ret +_TEXT ends +end + + + + diff --git a/AdvMan/AdvMan.cpp b/AdvMan/AdvMan.cpp new file mode 100644 index 0000000..88670a8 --- /dev/null +++ b/AdvMan/AdvMan.cpp @@ -0,0 +1,187 @@ +// AdvMan.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "AdvMan.h" + +#include "MainFrm.h" +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp + +BEGIN_MESSAGE_MAP(CAdvManApp, CWinApp) + //{{AFX_MSG_MAP(CAdvManApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp construction + +CAdvManApp::CAdvManApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CAdvManApp object + +CAdvManApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp initialization + +extern "C" +{ +#include "..\crashdump.h" + +int GetExeVersion(); +} + +int GetExeVersion() +{ + return 1; +} + +BOOL CAdvManApp::InitInstance() +{ +InitCrashDump(); + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Bredysoft")); + + + // To create the main window, this code creates a new frame window + // object and then sets it as the application's main window object. + + CMainFrame* pFrame = new CMainFrame; + m_pMainWnd = pFrame; + + // create and load the frame with its resources + + pFrame->LoadFrame(IDR_MAINFRAME, + WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, + NULL); + + + + + // The one and only window has been initialized, so show and update it. + pFrame->ShowWindow(SW_SHOW); + pFrame->UpdateWindow(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp message handlers + + + + + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CAdvManApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp message handlers + +struct TestDlgInfo +{ + MSG *msg; + BOOL found; + HWND exclude; +}; + +static BOOL WINAPI TestDlgWindows(HWND hWnd, LPARAM lParam) +{ + TestDlgInfo *nfo=(TestDlgInfo *)lParam; + if (hWnd==nfo->exclude) return TRUE; + if (SendMessage(hWnd,WM_APP+9998,0,(LPARAM)nfo->msg) || IsDialogMessage(hWnd,nfo->msg)) + { + nfo->found=TRUE; + return FALSE; + } + return TRUE; +} + +BOOL CAdvManApp::PreTranslateMessage(MSG *pMsg) +{ + TestDlgInfo nfo; + nfo.msg=pMsg; + nfo.found=FALSE; + nfo.exclude=*m_pMainWnd; + + EnumThreadWindows(GetCurrentThreadId(),TestDlgWindows,(LPARAM)&nfo); + return nfo.found; +} diff --git a/AdvMan/AdvMan.h b/AdvMan/AdvMan.h new file mode 100644 index 0000000..f08f54b --- /dev/null +++ b/AdvMan/AdvMan.h @@ -0,0 +1,55 @@ +// AdvMan.h : main header file for the ADVMAN application +// + +#if !defined(AFX_ADVMAN_H__A43CD3B3_508C_4DDB_B89C_50FE1291B8B9__INCLUDED_) +#define AFX_ADVMAN_H__A43CD3B3_508C_4DDB_B89C_50FE1291B8B9__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CAdvManApp: +// See AdvMan.cpp for the implementation of this class +// + +class CAdvManApp : public CWinApp +{ +public: + CAdvManApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAdvManApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + +public: + //{{AFX_MSG(CAdvManApp) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + virtual BOOL PreTranslateMessage(MSG *pMsg); +}; + + +///////////////////////////////////////////////////////////////////////////// + +extern CAdvManApp theApp; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADVMAN_H__A43CD3B3_508C_4DDB_B89C_50FE1291B8B9__INCLUDED_) diff --git a/AdvMan/AdvMan.rc b/AdvMan/AdvMan.rc new file mode 100644 index 0000000..1d9b914 --- /dev/null +++ b/AdvMan/AdvMan.rc @@ -0,0 +1,569 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Czech resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) +#ifdef _WIN32 +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\AdvMan.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP "res\\Toolbar.bmp" +IDR_TOOLEDITORY BITMAP "res\\editory.bmp" +IDR_PREKLADACE BITMAP "res\\prekladace.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Toolbar +// + +IDR_MAINFRAME TOOLBAR 16, 16 +BEGIN + BUTTON ID_FILE_NOVDOBRODRUST + BUTTON ID_FILE_NATIDOBRODRUSTV + SEPARATOR + BUTTON ID_NSTROJE_MAPEDIT + BUTTON ID_NSTROJE_TESTUJDOBRODRUSTV + SEPARATOR + BUTTON ID_APP_EXIT + SEPARATOR + BUTTON ID_APP_ABOUT +END + +IDR_TOOLEDITORY TOOLBAR 16, 15 +BEGIN + BUTTON ID_EDITORY_KOUZLATAB + BUTTON ID_EDITORY_POSTAVYTAB + BUTTON ID_EDITORY_DIALOGY + BUTTON ID_EDITORY_WEAPONSSCR + BUTTON ID_EDITORY_ITEMSPIC + BUTTON ID_EDITORY_ITEMSSCR +END + +IDR_PREKLADACE TOOLBAR 16, 15 +BEGIN + BUTTON ID_PEKLADAE_PELOKOUZLA + BUTTON ID_PEKLADAE_PELODIALOGY + BUTTON ID_PEKLADAE_PELOPOSTAVYTAB +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "Nové dobrodružstí", ID_FILE_NOVDOBRODRUST + MENUITEM SEPARATOR + MENUITEM "Načti dobrodružství", ID_FILE_NATIDOBRODRUSTV + MENUITEM "Znovu načíst", ID_FILE_ZNOVUNAST + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "Editory" + BEGIN + MENUITEM "KOUZLA.TAB", ID_EDITORY_KOUZLATAB + MENUITEM "POSTAVY.TAB", ID_EDITORY_POSTAVYTAB + MENUITEM "Dialogy", ID_EDITORY_DIALOGY + MENUITEM "ITEMS.SCR", ID_EDITORY_ITEMSSCR + MENUITEM "ITEMS.PIC", ID_EDITORY_ITEMSPIC + MENUITEM "WEAPONS.SCR", ID_EDITORY_WEAPONSSCR + MENUITEM "Soubor ADV", ID_EDITORY_SOUBORADV + END + POPUP "Překladače" + BEGIN + MENUITEM "Přelož kouzla", ID_PEKLADAE_PELOKOUZLA + MENUITEM "Přelož dialogy", ID_PEKLADAE_PELODIALOGY + MENUITEM "Přelož POSTAVY.TAB", ID_PEKLADAE_PELOPOSTAVYTAB + END + POPUP "Nástroje" + BEGIN + MENUITEM "MapEdit", ID_NSTROJE_MAPEDIT + MENUITEM "Testuj dobrodružství", ID_NSTROJE_TESTUJDOBRODRUSTV + MENUITEM SEPARATOR + MENUITEM "Tvůrce podlah", ID_NSTROJE_TVRCEPODLAH + MENUITEM "Tvůrce palet pro nestvůry", ID_NSTROJE_TVRCEPALETPRONESTVRY + + MENUITEM "Tvůrce ikon pro předměty", ID_NSTROJE_TVRCEIKONPROPEDMTY + + MENUITEM "Čtečka DDL souborů", ID_NSTROJE_TEKADDLSOUBOR + MENUITEM SEPARATOR + MENUITEM "Exportuj dobrodružství", ID_NSTROJE_EXPORTUJDOBRODRUSTV + + END + POPUP "&View" + BEGIN + MENUITEM "Hlavní toolbar", ID_VIEW_TOOLBAR + MENUITEM "Překladače", ID_VIEW_PREKLADACE + MENUITEM "Editory", 32810 + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About AdvMan...", ID_APP_ABOUT + END +END + +IDR_EDITORMENU MENU +BEGIN + POPUP "Soubor" + BEGIN + MENUITEM "Uložit", IDOK + MENUITEM SEPARATOR + MENUITEM "Konec", IDCANCEL + END + POPUP "Úpravy" + BEGIN + MENUITEM "Zpět", ID_PRAVY_UNDO + MENUITEM SEPARATOR + MENUITEM "Kopírovat", ID_UPRAVY_COPY + MENUITEM "Vyjmout", ID_UPRAVY_VYJMOUT + MENUITEM "Vložit", ID_UPRAVY_VLOZIT + MENUITEM "Vymazat", ID_UPRAVY_VYMAZAT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NOVEDOBR DIALOGEX 0, 0, 234, 297 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Založit nové dobrodružství" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + LTEXT "Jméno nového dobrodružství",IDC_STATIC,7,7,92,8 + EDITTEXT IDC_JMENO,7,18,159,12,ES_AUTOHSCROLL | WS_GROUP + GROUPBOX "Vyber organizaci projektu",IDC_STATIC,7,36,162,60, + WS_GROUP + CONTROL "Nová organizace (doporučeno)",IDC_ORGANIZACE,"Button", + BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,15,55,114,10 + CONTROL "Původní DOSová organizace (kompatibilní)",IDC_RADIO2, + "Button",BS_AUTORADIOBUTTON,15,66,152,10 + CONTROL "Vše v jedné složce (malé projeky)",IDC_RADIO3,"Button", + BS_AUTORADIOBUTTON,15,77,121,10 + GROUPBOX "Do nového projektu vložit",IDC_STATIC,7,98,162,82, + WS_GROUP + CONTROL "Také soubory pro editaci kouzel",IDC_KOUZLA,"Button", + BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,15,111,117,10 + CONTROL "Také soubory pro editaci dialogů",IDC_DIALOGY,"Button", + BS_AUTOCHECKBOX,15,123,119,10 + CONTROL "Také definice grafiky originální hry",IDC_DEFINICE, + "Button",BS_AUTOCHECKBOX,15,135,123,10 + CONTROL "Také všechny mapy z originální hry",IDC_MAPY,"Button", + BS_AUTOCHECKBOX,15,147,127,10 + GROUPBOX "Startovní mapa",IDC_STATIC,7,183,161,29,WS_GROUP + EDITTEXT IDC_STARTMAP,16,193,145,12,ES_AUTOHSCROLL | WS_GROUP + GROUPBOX "Počet členů družiny",IDC_STATIC,7,214,161,42,WS_GROUP + LTEXT "Nejméně",IDC_STATIC,15,228,29,8 + LTEXT "Nejvíce",IDC_STATIC,15,242,26,8 + EDITTEXT IDC_MINPOSTAV,53,226,16,12,ES_MULTILINE | WS_GROUP + EDITTEXT IDC_MAXPOSTAV,53,240,16,12,ES_MULTILINE | WS_GROUP + DEFPUSHBUTTON "OK",IDOK,177,7,50,14,WS_GROUP + PUSHBUTTON "Storno",IDCANCEL,177,24,50,14,NOT WS_TABSTOP + CONTROL "Také originální dialogy",IDC_ORIGDLGS,"Button", + BS_AUTOCHECKBOX,15,159,87,10 +END + +IDD_TEXTEDITOR DIALOGEX 0, 0, 599, 412 +STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +CAPTION "Textový editor" +MENU IDR_EDITORMENU +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Uložit (Ctrl+S)",IDOK,540,397,58,14 + EDITTEXT IDC_EDIT,44,0,553,395,ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_WANTRETURN | NOT WS_BORDER | + WS_VSCROLL | WS_HSCROLL,WS_EX_STATICEDGE +END + +IDD_DIALOGY DIALOGEX 0, 0, 334, 202 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialogy" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + PUSHBUTTON "Zavřít",IDCANCEL,267,24,60,14 + PUSHBUTTON "Upravit dialog",IDC_EDIT,267,68,60,14 + PUSHBUTTON "Přidat dialog",IDC_ADD,267,52,60,14 + PUSHBUTTON "Vymazat dialog",IDC_DELETE,267,85,60,14 + CONTROL "List1",IDC_DLGLIST,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | LVS_EDITLABELS | WS_BORDER | + WS_TABSTOP,7,7,256,188 + PUSHBUTTON "Obnovit",IDC_RESCAN,267,181,60,14 + DEFPUSHBUTTON "OK",IDOK,267,7,60,14 +END + +IDD_NOVYDIALOG DIALOG 0, 0, 214, 105 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Nový dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,157,67,50,14 + PUSHBUTTON "Cancel",IDCANCEL,157,84,50,14 + LTEXT "Popis dialogu:",IDC_STATIC,7,7,45,8 + EDITTEXT IDC_POPIS,7,18,200,12,ES_AUTOHSCROLL + LTEXT "Jméno souboru dialogu bez přípony (.dlg) - 8 znaků", + IDC_STATIC,7,32,162,8 + COMBOBOX IDC_JMENO,7,43,73,61,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + LTEXT "Čislo dialogu:",IDC_STATIC,7,60,42,8 + LTEXT "Uplatní se pouze pro nově založený dialog",IDC_STATIC,7, + 89,134,8 + COMBOBOX IDC_CISLO,7,72,33,105,CBS_DROPDOWN | CBS_SORT | + WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_NOVEDOBR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 227 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END + + IDD_TEXTEDITOR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 592 + TOPMARGIN, 7 + BOTTOMMARGIN, 405 + END + + IDD_DIALOGY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 327 + TOPMARGIN, 7 + BOTTOMMARGIN, 195 + END + + IDD_NOVYDIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 207 + TOPMARGIN, 7 + BOTTOMMARGIN, 98 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_NOTEPADICON ICON "idc_note.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDR_MAINFRAME "Adventure Manager" + IDS_NOVEDOBRODRUZSTVIDOKONCENO + "Průvodce novým dobrodružstvím dokončil všechny úkoly.\r\n\r\nPokud se zobrazila nějaká chyba, bude nutné po opravě chyby příkaz opakovat, jinak nebude dobrodružství hratelné." + IDS_ADVFILTER "Dobrodružství Skeldalu|*.adv|Všechny soubory|*.*||" + IDS_CHYBAPRICTENI "Chyba při čtení souboru dobrodružství" + IDS_MAINFRAMETITLE "%s - Adventure Manager " + IDS_UNTITLED "Nepojmenované.ADV" + IDS_CANNOTEXECUTE "Nemohu spustit aplikaci '%1'" + IDS_NEMOHUNAJITNICOD "Pozor! Nemohu najít následující soubor(y):\r\n\r\n%1\r\n\r\nChybějící soubory mohou způsobit, že dobrodružství nebude možné hrát." + IDS_EDITADVWARN "Pozor! Změny v souboru ADV se neprojeví ihned. Po uložení nechte znovu načíst dobrodružství pomocí funkce Soubor -> Znovu načíst." + IDS_DLGNAME "Jméno" + IDS_DLGDESC "Popis" + IDS_DLGID "ID" + IDS_UNABLETOSAVEDIALOGYDLG + "Nemohu uložit soubor DIALOGY.DLG. Nastala nějaká chyba." + IDS_NODESC "" +END + +STRINGTABLE +BEGIN + AFX_IDS_APP_TITLE "AdvMan" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright\nAbout" + ID_APP_EXIT "Quit the application; prompts to save documents\nExit" +END + +STRINGTABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane\nNext Pane" + ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane" +END + +STRINGTABLE +BEGIN + ID_WINDOW_SPLIT "Split the active window into panes\nSplit" +END + +STRINGTABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection\nErase" + ID_EDIT_CLEAR_ALL "Erase everything\nErase All" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut" + ID_EDIT_FIND "Find the specified text\nFind" + ID_EDIT_PASTE "Insert Clipboard contents\nPaste" + ID_EDIT_REPEAT "Repeat the last action\nRepeat" + ID_EDIT_REPLACE "Replace specific text with different text\nReplace" + ID_EDIT_SELECT_ALL "Select the entire document\nSelect All" + ID_EDIT_UNDO "Undo the last action\nUndo" + ID_EDIT_REDO "Redo the previously undone action\nRedo" +END + +STRINGTABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" + ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +#endif // Czech resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About AdvMan" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "AdvMan Version 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX + LTEXT "Copyright (C) 2005",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\AdvMan.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS +BEGIN + "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT + VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT + VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT + VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT + VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT + VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT + VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT + "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT + "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "FileDescription", "AdvMan MFC Application" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "AdvMan" + VALUE "LegalCopyright", "Copyright (C) 2005" + VALUE "OriginalFilename", "AdvMan.EXE" + VALUE "ProductName", "AdvMan Application" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\AdvMan.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/AdvMan/AdvMan.sln b/AdvMan/AdvMan.sln new file mode 100644 index 0000000..d4e56d1 --- /dev/null +++ b/AdvMan/AdvMan.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvMan", "AdvMan.vcproj", "{D38E31E6-CC5E-4C25-B966-85BF48E8C53E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {D38E31E6-CC5E-4C25-B966-85BF48E8C53E}.Debug.ActiveCfg = Debug|Win32 + {D38E31E6-CC5E-4C25-B966-85BF48E8C53E}.Debug.Build.0 = Debug|Win32 + {D38E31E6-CC5E-4C25-B966-85BF48E8C53E}.Release.ActiveCfg = Release|Win32 + {D38E31E6-CC5E-4C25-B966-85BF48E8C53E}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/AdvMan/AdvMan.vcproj b/AdvMan/AdvMan.vcproj new file mode 100644 index 0000000..b3f0061 --- /dev/null +++ b/AdvMan/AdvMan.vcproj @@ -0,0 +1,525 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AdvMan/ChildView.cpp b/AdvMan/ChildView.cpp new file mode 100644 index 0000000..d4dc2da --- /dev/null +++ b/AdvMan/ChildView.cpp @@ -0,0 +1,57 @@ +// ChildView.cpp : implementation of the CChildView class +// + +#include "stdafx.h" +#include "AdvMan.h" +#include "ChildView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CChildView + +CChildView::CChildView() +{ +} + +CChildView::~CChildView() +{ +} + + +BEGIN_MESSAGE_MAP(CChildView,CWnd ) + //{{AFX_MSG_MAP(CChildView) + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CChildView message handlers + +BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) +{ + if (!CWnd::PreCreateWindow(cs)) + return FALSE; + + cs.dwExStyle |= WS_EX_CLIENTEDGE; + cs.style &= ~WS_BORDER; + cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, + ::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL); + + return TRUE; +} + +void CChildView::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // TODO: Add your message handler code here + + // Do not call CWnd::OnPaint() for painting messages +} + diff --git a/AdvMan/ChildView.h b/AdvMan/ChildView.h new file mode 100644 index 0000000..1a31b1d --- /dev/null +++ b/AdvMan/ChildView.h @@ -0,0 +1,51 @@ +// ChildView.h : interface of the CChildView class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CHILDVIEW_H__C7E216F0_6DED_46F2_9E4F_0F71719D08CA__INCLUDED_) +#define AFX_CHILDVIEW_H__C7E216F0_6DED_46F2_9E4F_0F71719D08CA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CChildView window + +class CChildView : public CWnd +{ +// Construction +public: + CChildView(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChildView) + protected: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CChildView(); + + // Generated message map functions +protected: + //{{AFX_MSG(CChildView) + afx_msg void OnPaint(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHILDVIEW_H__C7E216F0_6DED_46F2_9E4F_0F71719D08CA__INCLUDED_) diff --git a/AdvMan/DlgDialogy.cpp b/AdvMan/DlgDialogy.cpp new file mode 100644 index 0000000..4ca4f96 --- /dev/null +++ b/AdvMan/DlgDialogy.cpp @@ -0,0 +1,264 @@ +// DlgDialogy.cpp : implementation file +// + +#include "stdafx.h" +#include "AdvMan.h" +#include "DlgDialogy.h" +#include "../cztable.h" +#include "MainFrm.h" +#include "DlgNovyDialog.h" +#include +#include ".\dlgdialogy.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// DlgDialogy dialog + + +DlgDialogy::DlgDialogy(CWnd* pParent /*=NULL*/) + : CDialog(DlgDialogy::IDD, pParent) +{ + //{{AFX_DATA_INIT(DlgDialogy) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void DlgDialogy::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(DlgDialogy) + DDX_Control(pDX, IDC_DLGLIST, wList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(DlgDialogy, CDialog) + //{{AFX_MSG_MAP(DlgDialogy) + ON_BN_CLICKED(IDC_RESCAN, OnRescan) + ON_BN_CLICKED(IDC_DELETE, OnDelete) + ON_BN_CLICKED(IDC_EDIT, OnEdit) + ON_NOTIFY(LVN_COLUMNCLICK, IDC_DLGLIST, OnColumnclickDlglist) + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_NOTIFY(NM_DBLCLK, IDC_DLGLIST, OnNMDblclkDlglist) + //}}AFX_MSG_MAP + ON_NOTIFY(LVN_ENDLABELEDIT, IDC_DLGLIST, OnLvnEndlabeleditDlglist) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// DlgDialogy message handlers + +BOOL DlgDialogy::OnInitDialog() +{ + CDialog::OnInitDialog(); + + wList.InsertColumn(0,CString(MAKEINTRESOURCE(IDS_DLGDESC)),LVCFMT_LEFT,200,0); + wList.InsertColumn(1,CString(MAKEINTRESOURCE(IDS_DLGNAME)),LVCFMT_LEFT,100,1); + wList.InsertColumn(2,CString(MAKEINTRESOURCE(IDS_DLGID)),LVCFMT_CENTER,30,2); + ListView_SetExtendedListViewStyleEx(wList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); + OnRescan(); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +int DlgDialogy::GetDialogID(const char *name) +{ + Pathname dialogPath=_dlgpath; + dialogPath.SetFilename(name); + FILE *f=fopen(dialogPath,"r"); + if (f==0) return -1; + int id; + char dialog[40]; + if (fscanf(f," %40[^\r\n\t (] ( %d )",dialog,&id)==2) + { + if (stricmp(dialog,"DIALOG")==0) + { + fclose(f); + return id; + } + } + fclose(f); + return -1; +} + +void DlgDialogy::LoadDialogyDlg() +{ + FILE *f=fopen(_dlgpath,"r"); + if (f==0) return; + + int p=0; + + while (!feof(f)) + { + char name[80]; + char desc[256]; + name[0]=0; + desc[0]=0; + fscanf(f,"%80s",name); + fscanf(f," %250[^\r\n]",desc); + kamenik2windows(name,strlen(name),name); + kamenik2windows(desc,strlen(desc),desc); + int row; + + if (name[0]!=0 || desc[0]!=0) + { + row=wList.InsertItem(p,desc,0); + wList.SetItemText(row,1,name); + int dlgId=GetDialogID(name); + wList.SetItemText(row,2,itoa(dlgId,desc,10)); + p++; + } + } + fclose(f); +} + +void DlgDialogy::OnRescan() +{ + wList.DeleteAllItems(); + LoadDialogyDlg(); +} + +void DlgDialogy::OnDelete() +{ + int w; + while ((w=wList.GetNextItem(-1,LVNI_SELECTED))!=-1) + { + wList.DeleteItem(w); + } +} + +void DlgDialogy::OnEdit() +{ + CString name; + int w=-1; + while ((w=wList.GetNextItem(w,LVNI_SELECTED))!=-1) + { + name=wList.GetItemText(w,1); + Pathname editName=_dlgpath; + editName.SetFilename(name); + _mainFrame->OpenEditor(editName); + } +} + +void DlgDialogy::OnOK() +{ + FILE *f=fopen(_dlgpath,"w"); + if (f==0) + { + AfxMessageBox(IDS_UNABLETOSAVEDIALOGYDLG,MB_ICONEXCLAMATION); + return; + } + + for (int i=0,cnt=wList.GetItemCount();iiSubItem; + wList.SortItems(CompareFunc,(DWORD)this); + + *pResult = 0; +} + + +int DlgDialogy::CompareItems(int item1, int item2) +{ + switch (_sortItem) + { + case 0: + { + CString a=wList.GetItemText(item1,0); + CString b=wList.GetItemText(item2,0); + return stricmp(a,b); + } + case 1: + { + CString a=wList.GetItemText(item1,1); + CString b=wList.GetItemText(item2,1); + return stricmp(a,b); + } + case 2: + { + char buff[20]; + int a,b; + wList.GetItemText(item1,2,buff,20);a=atoi(buff); + wList.GetItemText(item2,2,buff,20);b=atoi(buff); + return (a>b)-(a_dlgpath; + nw.sourceLst=&wList; + if (nw.DoModal()==IDOK) + { + int p=wList.InsertItem(wList.GetItemCount(),nw.vPopis); + Pathname dlgName=_dlgpath; + dlgName.SetFiletitle(nw.vJmeno); + dlgName.SetExtension(".dlg"); + wList.SetItemText(p,1,dlgName.GetFilename()); + if (_access(dlgName,0)!=0) + { + FILE *f=fopen(dlgName,"w"); + fprintf(f,"DIALOG(%d)\n",nw.vCislo); + fprintf(f,"{\nPICTURE (\"SCREEN\")\nDESC (\"Popis\")\nSTANDARD (1)\n}\n\nSENTENCE (1,0)\n{\n\n}"); + fclose(f); + } + int num=GetDialogID(dlgName.GetFilename()); + char buff[20]; + wList.SetItemText(p,2,itoa(num,buff,10)); + } +} + + +void DlgDialogy::OnNMDblclkDlglist(NMHDR *pNMHDR, LRESULT *pResult) +{ + OnEdit(); + *pResult = 0; +} + +void DlgDialogy::OnLvnEndlabeleditDlglist(NMHDR *pNMHDR, LRESULT *pResult) +{ + NMLVDISPINFO *pDispInfo = reinterpret_cast(pNMHDR); + // TODO: Add your control notification handler code here + *pResult = 1; +} diff --git a/AdvMan/DlgDialogy.h b/AdvMan/DlgDialogy.h new file mode 100644 index 0000000..10efb2d --- /dev/null +++ b/AdvMan/DlgDialogy.h @@ -0,0 +1,76 @@ +#if !defined(AFX_DLGDIALOGY_H__E47269D5_6849_42F5_AF6F_32EEEE32104D__INCLUDED_) +#define AFX_DLGDIALOGY_H__E47269D5_6849_42F5_AF6F_32EEEE32104D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgDialogy.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// DlgDialogy dialog + +#define MAXDIALOGY 240 + +class CMainFrame; + +class DlgDialogy : public CDialog +{ +// Construction +public: + void LoadDialogyDlg(); + DlgDialogy(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(DlgDialogy) + enum { IDD = IDD_DIALOGY }; + CListCtrl wList; + //}}AFX_DATA + + Pathname _dlgpath; + CMainFrame *_mainFrame; + int _sortItem; + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(DlgDialogy) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(DlgDialogy) + virtual BOOL OnInitDialog(); + afx_msg void OnRescan(); + afx_msg void OnDelete(); + afx_msg void OnEdit(); + virtual void OnOK(); + virtual void OnCancel(); + afx_msg void OnColumnclickDlglist(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnAdd(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + int GetDialogID(const char *name); + static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) + { + DlgDialogy *self=(DlgDialogy *)lParamSort; + return self->CompareItems(lParam1,lParam2); + } + + int CompareItems(int item1, int item2); + + +public: + afx_msg void OnNMDblclkDlglist(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnLvnEndlabeleditDlglist(NMHDR *pNMHDR, LRESULT *pResult); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGDIALOGY_H__E47269D5_6849_42F5_AF6F_32EEEE32104D__INCLUDED_) diff --git a/AdvMan/DlgNoveDobr.cpp b/AdvMan/DlgNoveDobr.cpp new file mode 100644 index 0000000..9c30222 --- /dev/null +++ b/AdvMan/DlgNoveDobr.cpp @@ -0,0 +1,83 @@ +// DlgNoveDobr.cpp : implementation file +// + +#include "stdafx.h" +#include "AdvMan.h" +#include "DlgNoveDobr.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// DlgNoveDobr dialog + + +DlgNoveDobr::DlgNoveDobr(CWnd* pParent /*=NULL*/) + : CDialog(DlgNoveDobr::IDD, pParent) +{ + //{{AFX_DATA_INIT(DlgNoveDobr) + vJmeno = _T(""); + vKouzla = TRUE; + vMapy = FALSE; + vDialogy = TRUE; + vDefinice = FALSE; + vOrganizace = 0; + vStartMap = _T("start.map"); + vMaxPostav = 3; + vMinPostav = 3; + //}}AFX_DATA_INIT +} + + +void DlgNoveDobr::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(DlgNoveDobr) + DDX_Text(pDX, IDC_JMENO, vJmeno); + DDX_Check(pDX, IDC_KOUZLA, vKouzla); + DDX_Check(pDX, IDC_MAPY, vMapy); + DDX_Check(pDX, IDC_DIALOGY, vDialogy); + DDX_Check(pDX, IDC_DEFINICE, vDefinice); + DDX_Radio(pDX, IDC_ORGANIZACE, vOrganizace); + DDX_Text(pDX, IDC_STARTMAP, vStartMap); + DDX_Check(pDX, IDC_ORIGDLGS, vDialogyDlg); + DDV_MaxChars(pDX, vStartMap, 12); + //}}AFX_DATA_MAP + DDX_Text(pDX, IDC_MINPOSTAV, vMinPostav); + DDV_MinMaxUInt(pDX, vMinPostav, 1, 6); + DDX_Text(pDX, IDC_MAXPOSTAV, vMaxPostav); + DDV_MinMaxUInt(pDX, vMaxPostav, vMinPostav, 6); +} + + +BEGIN_MESSAGE_MAP(DlgNoveDobr, CDialog) + //{{AFX_MSG_MAP(DlgNoveDobr) + ON_EN_CHANGE(IDC_JMENO, OnChangeJmeno) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// DlgNoveDobr message handlers + +void DlgNoveDobr::DialogRules() +{ + GetDlgItem(IDOK)->EnableWindow(GetDlgItem(IDC_JMENO)->GetWindowTextLength()); +} + +BOOL DlgNoveDobr::OnInitDialog() +{ + CDialog::OnInitDialog(); + + DialogRules(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void DlgNoveDobr::OnChangeJmeno() +{ + DialogRules(); +} diff --git a/AdvMan/DlgNoveDobr.h b/AdvMan/DlgNoveDobr.h new file mode 100644 index 0000000..a3db1f4 --- /dev/null +++ b/AdvMan/DlgNoveDobr.h @@ -0,0 +1,57 @@ +#if !defined(AFX_DLGNOVEDOBR_H__410472E5_5BCF_4CE8_8FE3_10693C0F05F7__INCLUDED_) +#define AFX_DLGNOVEDOBR_H__410472E5_5BCF_4CE8_8FE3_10693C0F05F7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgNoveDobr.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// DlgNoveDobr dialog + +class DlgNoveDobr : public CDialog +{ +// Construction +public: + void DialogRules(); + DlgNoveDobr(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(DlgNoveDobr) + enum { IDD = IDD_NOVEDOBR }; + CString vJmeno; + BOOL vKouzla; + BOOL vMapy; + BOOL vDialogy; + BOOL vDefinice; + BOOL vDialogyDlg; + int vOrganizace; + CString vStartMap; + UINT vMaxPostav; + UINT vMinPostav; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(DlgNoveDobr) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(DlgNoveDobr) + virtual BOOL OnInitDialog(); + afx_msg void OnChangeJmeno(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGNOVEDOBR_H__410472E5_5BCF_4CE8_8FE3_10693C0F05F7__INCLUDED_) diff --git a/AdvMan/DlgNovyDialog.cpp b/AdvMan/DlgNovyDialog.cpp new file mode 100644 index 0000000..67f9b44 --- /dev/null +++ b/AdvMan/DlgNovyDialog.cpp @@ -0,0 +1,127 @@ +// DlgNovyDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "AdvMan.h" +#include "DlgNovyDialog.h" +#include + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// DlgNovyDialog dialog + + +DlgNovyDialog::DlgNovyDialog(CWnd* pParent /*=NULL*/) + : CDialog(DlgNovyDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(DlgNovyDialog) + vCislo = 0; + vJmeno = _T(""); + vPopis = _T(""); + //}}AFX_DATA_INIT +} + + +void DlgNovyDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(DlgNovyDialog) + DDX_Control(pDX, IDC_CISLO, wCislo); + DDX_Control(pDX, IDC_JMENO, wJmeno); + DDX_Text(pDX, IDC_CISLO, vCislo); + DDV_MinMaxInt(pDX, vCislo, 1, 254); + DDX_CBString(pDX, IDC_JMENO, vJmeno); + DDV_MaxChars(pDX, vJmeno, 8); + DDX_Text(pDX, IDC_POPIS, vPopis); + DDV_MaxChars(pDX, vPopis, 50); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(DlgNovyDialog, CDialog) + //{{AFX_MSG_MAP(DlgNovyDialog) + ON_CBN_EDITCHANGE(IDC_JMENO, OnEditchangeJmeno) + ON_CBN_SELENDOK(IDC_JMENO, OnSelendokJmeno) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// DlgNovyDialog message handlers + +BOOL DlgNovyDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + + bool idlist[256]; + memset(idlist,0,sizeof(idlist)); + + dlgSource.SetFilename("*.dlg"); + CFileFind fnd; + BOOL next; + if (fnd.FindFile(dlgSource)) do + { + next=fnd.FindNextFile(); + CString name=fnd.GetFileTitle(); + name.MakeLower(); + wJmeno.AddString(name); + }while (next); + + int i,cnt; + for (i=0,cnt=sourceLst->GetItemCount();iGetItemText(i,1); + dlgSource.SetFilename(name); + name=dlgSource.GetTitle(); + name.MakeLower(); + int p=wJmeno.FindStringExact(-1,name); + if (p!=-1) wJmeno.DeleteString(p); + + name=sourceLst->GetItemText(i,2); + p=atoi(name); + if (p>=0 && p<256) idlist[p]=true; + } + bool x=true; + for (i=1;i<254;i++) if (!idlist[i]) + { + char buff[50]; + sprintf(buff,"%3d",i); + wCislo.AddString(buff); + if (x) + { + wCislo.SetWindowText(buff); + x=false; + } + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void DlgNovyDialog::DialogRules() +{ + BOOL ok=wJmeno.GetWindowTextLength() && wCislo.GetWindowTextLength(); + GetDlgItem(IDOK)->EnableWindow(ok); + CString name; + wJmeno.GetWindowText(name); + dlgSource.SetFiletitle(name); + wCislo.EnableWindow(access(dlgSource,0)==-1); +} + +void DlgNovyDialog::OnEditchangeJmeno() +{ + DialogRules(); +} + +void DlgNovyDialog::OnSelendokJmeno() +{ + int p=wJmeno.GetCurSel(); + CString z; + wJmeno.GetLBText(p,z); + wJmeno.SetWindowText(z); + DialogRules(); +} diff --git a/AdvMan/DlgNovyDialog.h b/AdvMan/DlgNovyDialog.h new file mode 100644 index 0000000..526175a --- /dev/null +++ b/AdvMan/DlgNovyDialog.h @@ -0,0 +1,57 @@ +#if !defined(AFX_DLGNOVYDIALOG_H__00136ADF_E2C6_4081_83AB_D5110EE43612__INCLUDED_) +#define AFX_DLGNOVYDIALOG_H__00136ADF_E2C6_4081_83AB_D5110EE43612__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DlgNovyDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// DlgNovyDialog dialog + +class DlgDialogy; + +class DlgNovyDialog : public CDialog +{ +// Construction +public: + void DialogRules(); + DlgNovyDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(DlgNovyDialog) + enum { IDD = IDD_NOVYDIALOG }; + CComboBox wCislo; + CComboBox wJmeno; + int vCislo; + CString vJmeno; + CString vPopis; + //}}AFX_DATA + + CListCtrl *sourceLst; + Pathname dlgSource; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(DlgNovyDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(DlgNovyDialog) + virtual BOOL OnInitDialog(); + afx_msg void OnEditchangeJmeno(); + afx_msg void OnSelendokJmeno(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGNOVYDIALOG_H__00136ADF_E2C6_4081_83AB_D5110EE43612__INCLUDED_) diff --git a/AdvMan/FCS_tasker.h b/AdvMan/FCS_tasker.h new file mode 100644 index 0000000..e69de29 diff --git a/AdvMan/FS_tasker.h b/AdvMan/FS_tasker.h new file mode 100644 index 0000000..e69de29 diff --git a/AdvMan/MainFrm.cpp b/AdvMan/MainFrm.cpp new file mode 100644 index 0000000..9cdacb8 --- /dev/null +++ b/AdvMan/MainFrm.cpp @@ -0,0 +1,677 @@ +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "AdvMan.h" +#include "..\cztable.h" + +#include "MainFrm.h" +#include "DlgDialogy.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_WM_SETFOCUS() + ON_WM_INITMENUPOPUP() + ON_COMMAND(ID_FILE_NOVDOBRODRUST, OnFileNovdobrodrust) + ON_COMMAND(ID_FILE_NATIDOBRODRUSTV, OnFileNatidobrodrustv) + ON_COMMAND(ID_EDITORY_KOUZLATAB, OnEditoryKouzlatab) + ON_COMMAND(ID_EDITORY_POSTAVYTAB, OnEditoryPostavytab) + ON_COMMAND(ID_EDITORY_ITEMSSCR, OnEditoryItemsscr) + ON_COMMAND(ID_EDITORY_ITEMSPIC, OnEditoryItemspic) + ON_COMMAND(ID_EDITORY_WEAPONSSCR, OnEditoryWeaponsscr) + ON_WM_DESTROY() + ON_COMMAND(ID_PEKLADAE_PELOKOUZLA, OnPekladaePelokouzla) + ON_COMMAND(ID_PEKLADAE_PELODIALOGY, OnPekladaePelodialogy) + ON_COMMAND(ID_PEKLADAE_PELOPOSTAVYTAB, OnPekladaePelopostavytab) + ON_COMMAND(ID_NSTROJE_MAPEDIT, OnNstrojeMapedit) + ON_COMMAND(ID_NSTROJE_TESTUJDOBRODRUSTV, OnNstrojeTestujdobrodrustv) + ON_COMMAND(ID_NSTROJE_TVRCEPODLAH, OnNstrojeTvrcepodlah) + ON_COMMAND(ID_NSTROJE_TVRCEPALETPRONESTVRY, OnNstrojeTvrcepaletpronestvry) + ON_COMMAND(ID_NSTROJE_TVRCEIKONPROPEDMTY, OnNstrojeTvrceikonpropedmty) + ON_COMMAND(ID_EDITORY_SOUBORADV, OnEditorySouboradv) + ON_COMMAND(ID_FILE_ZNOVUNAST, OnFileZnovunast) + ON_UPDATE_COMMAND_UI(ID_FILE_ZNOVUNAST, OnUpdateFileZnovunast) + ON_COMMAND(ID_EDITORY_DIALOGY, OnEditoryDialogy) + ON_COMMAND_EX(ID_VIEW_EDITORY,OnBarCheck) + ON_COMMAND_EX(ID_VIEW_PREKLADACE,OnBarCheck) + ON_UPDATE_COMMAND_UI(ID_VIEW_EDITORY,OnUpdateControlBarMenu) + ON_UPDATE_COMMAND_UI(ID_VIEW_PREKLADACE,OnUpdateControlBarMenu) + ON_UPDATE_COMMAND_UI_RANGE(ID_EDITORY_KOUZLATAB,ID_EDITORY_WEAPONSSCR,OnUpdateEditory) + ON_UPDATE_COMMAND_UI_RANGE(ID_PEKLADAE_PELOKOUZLA,ID_PEKLADAE_PELOPOSTAVYTAB,OnUpdateEditory) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +static UINT indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here + +} + +CMainFrame::~CMainFrame() +{ + +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + // create a view to occupy the client area of the frame + if (!m_wndView.Create(ES_READONLY|WS_VISIBLE|WS_CHILD|ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL,CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST)) + { + TRACE0("Failed to create view window\n"); + return -1; + } + + if (!m_wndToolBar.CreateEx(this, TBSTYLE_BUTTON, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_TOOLTIPS | CBRS_FLYBY |BTNS_AUTOSIZE | CBRS_SIZE_DYNAMIC) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndEditoryBar.CreateEx(this, TBSTYLE_BUTTON, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_TOOLTIPS | CBRS_FLYBY |BTNS_AUTOSIZE | CBRS_SIZE_DYNAMIC,CRect(0,0,0,0),ID_VIEW_EDITORY) || + !m_wndEditoryBar.LoadToolBar(IDR_TOOLEDITORY)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndPrekladaceBar.CreateEx(this, TBSTYLE_BUTTON, WS_CHILD | WS_VISIBLE | CBRS_TOP + | CBRS_TOOLTIPS | CBRS_FLYBY |BTNS_AUTOSIZE | CBRS_SIZE_DYNAMIC,CRect(0,0,0,0),ID_VIEW_PREKLADACE) || + !m_wndPrekladaceBar.LoadToolBar(IDR_PREKLADACE)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + // TODO: Delete these three lines if you don't want the toolbar to + // be dockable + ShowWindow(SW_SHOW); + m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); + m_wndEditoryBar.EnableDocking(CBRS_ALIGN_ANY); + m_wndPrekladaceBar.EnableDocking(CBRS_ALIGN_ANY); + EnableDocking(CBRS_ALIGN_ANY); + DockControlBar(&m_wndToolBar); + DockControlBar(&m_wndEditoryBar); + DockControlBar(&m_wndPrekladaceBar); + UpdateWindow(); + CRect rc; + GetClientRect(&rc); + ClientToScreen(&rc); + DockControlBar(&m_wndEditoryBar,(UINT)0,CRect(rc.left+180,rc.top+5,rc.left+180,rc.top+5)); + DockControlBar(&m_wndPrekladaceBar,(UINT)0,CRect(rc.left+350,rc.top+5,rc.left+350,rc.top+5)); + + _adv=0; + CString untitled; + untitled.LoadString(IDS_UNTITLED); + SetTitle(untitled); + + SetClassLong(*this,GCL_HICON,(LONG)(theApp.LoadIcon(IDR_MAINFRAME))); + + return 0; +} + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + if( !CFrameWnd::PreCreateWindow(cs) ) + return FALSE; + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + cs.dwExStyle &= ~WS_EX_CLIENTEDGE; + cs.lpszClass = AfxRegisterWndClass(0); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers +void CMainFrame::OnSetFocus(CWnd* pOldWnd) +{ + // forward focus to the view window + m_wndView.SetFocus(); +} + +BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) +{ + // let the view have first crack at the command + if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) + return TRUE; + + // otherwise, do default handling + return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + + +void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) +{ + if (_adv==0) + { + for (int i=0,cnt=pPopupMenu->GetMenuItemCount();iGetMenuItemID(i); + if (id!=ID_FILE_NOVDOBRODRUST && id!=ID_FILE_NATIDOBRODRUSTV && id!=ID_APP_EXIT && + id!=ID_VIEW_TOOLBAR && id!=ID_VIEW_STATUS_BAR && id!=ID_APP_ABOUT && id!=ID_VIEW_EDITORY) + pPopupMenu->EnableMenuItem(i,MF_GRAYED|MF_BYPOSITION); + } + } + else + CFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); +} + +#include "DlgNoveDobr.h" + +static str_add_wildcard(TSTR_LIST *lst, const char *mask) +{ + CFileFind fnd; + BOOL nxt=fnd.FindFile(mask); + if (nxt==FALSE) + { + CString msg; + AfxFormatString1(msg,IDS_NEMOHUNAJITNICOD,mask); + AfxMessageBox(msg,MB_ICONEXCLAMATION); + } + while (nxt) + { + nxt=fnd.FindNextFile(); + str_add(lst,fnd.GetFilePath()); + } +} + +void CMainFrame::OnFileNovdobrodrust() +{ + DlgNoveDobr dlg; + int id=dlg.DoModal(); + if (id==IDOK) + { + release_list(_adv); + _adv=create_list(10); + CString baseMap=_T("adv\\")+dlg.vJmeno+_T("\\"); + add_field_txt(&_adv,_T("CESTA_MAPY"),baseMap); + CString cestaGrafika; + CString cestaDialogy; + CString cestaEnemy; + CString cestaItemy; + CString cestaPozice; + CString cestaZvuky; + CString cestaBasicGr; + switch (dlg.vOrganizace) + { + case 0: + cestaGrafika=baseMap+_T("GRFSTENY\\"); + cestaDialogy=baseMap+_T("GRFDIALG\\"); + cestaEnemy=baseMap+_T("GRFENEMY\\"); + cestaItemy=baseMap+_T("GRFITEMS\\"); + cestaPozice=baseMap+_T("SAVEGAME\\"); + cestaZvuky=baseMap+_T("SOUNDS\\"); + cestaBasicGr=baseMap+_T("GRFBASIC\\"); + break; + case 1: + cestaGrafika=baseMap+_T("graphics\\"); + cestaDialogy=baseMap+_T("graphics\\dialogs\\"); + cestaEnemy=baseMap+_T("graphics\\enemies\\"); + cestaItemy=baseMap+_T("graphics\\items\\"); + cestaPozice=baseMap+_T("SAVEGAME\\"); + cestaZvuky=baseMap+_T("SAMPLES\\"); + cestaBasicGr=baseMap+_T("graphics\\basic\\"); + break; + case 2: + cestaGrafika=baseMap; + cestaDialogy=baseMap; + cestaEnemy=baseMap; + cestaItemy=baseMap; + cestaPozice=baseMap+_T("SAVEGAME\\"); + cestaZvuky=baseMap; + cestaBasicGr=baseMap; + break; + } + + add_field_txt(&_adv,_T("CESTA_GRAFIKA"),cestaGrafika); + add_field_txt(&_adv,_T("CESTA_DIALOGY"),cestaDialogy); + add_field_txt(&_adv,_T("CESTA_ENEMY"),cestaEnemy); + add_field_txt(&_adv,_T("CESTA_ITEMY"),cestaItemy); + add_field_txt(&_adv,_T("CESTA_POZICE"),cestaPozice); + add_field_txt(&_adv,_T("CESTA_ZVUKY"),cestaZvuky); + add_field_txt(&_adv,_T("CESTA_BGRAFIKA"),cestaBasicGr); + + add_field_txt(&_adv,_T("DEFAULT_MAP"),dlg.vStartMap); + add_field_num(&_adv,_T("CHAR_MIN"),dlg.vMinPostav); + add_field_num(&_adv,_T("CHAR_MAX"),dlg.vMaxPostav); + add_field_num(&_adv,_T("PATCH"),1); + + Pathname pth=Pathname::GetExePath(); + pth.SetFiletitle(dlg.vJmeno); + pth.SetExtension(_T(".adv")); + + save_config(_adv,pth); + + _advName=pth; + _advPath=pth.GetDirectoryWithDrive(); + + SetTitle(pth); + + + Pathname exePath=Pathname::GetExePath(); + + pth.CreateFolder(exePath.GetDirectoryWithDrive()+baseMap); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaGrafika); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaDialogy); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaItemy); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaEnemy); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaPozice); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaZvuky); + pth.CreateFolder(exePath.GetDirectoryWithDrive()+cestaBasicGr); + + CString basePath=pth.GetDirectoryWithDrive(); + + TSTR_LIST fileList=create_list(10); + str_add_wildcard(&fileList,basePath+_T("maps\\*.dat")); + if (!dlg.vDefinice) str_add_wildcard(&fileList,basePath+_T("AdvManData\\weapons.scr")); + if (!dlg.vDefinice) str_add_wildcard(&fileList,basePath+_T("AdvManData\\items.scr")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\items.pic")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\*.lst")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\postavy.def")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\postavy.tab")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\predmety.tab")); + if (dlg.vKouzla) + { + str_add_wildcard(&fileList,basePath+_T("AdvManData\\kouzla.def")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\kouzla.tab")); + } + if (dlg.vDialogy) + { + str_add_wildcard(&fileList,basePath+_T("AdvManData\\dialogy.def")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\dlgsecrt.def")); + } + if (dlg.vDefinice) + { + str_add_wildcard(&fileList,basePath+_T("AdvManData\\*.scr")); + str_add_wildcard(&fileList,basePath+_T("AdvManData\\*.txt")); + } + if (dlg.vMapy) + { + str_add_wildcard(&fileList,basePath+_T("maps\\*.map")); + } + if (dlg.vDialogyDlg) + { + str_add_wildcard(&fileList,basePath+_T("AdvManData\\*.dlg")); + } + int totalszneed=0; + int i,cnt; + for (i=0,cnt=str_count(fileList);imessage,pMsg->wParam,pMsg->lParam); + pMsg->time=res; + return res==0; +} + + +LRESULT CMainFrame::BroadcastMessage(UINT msg, WPARAM wParam, LPARAM lParam) +{ + MSG Msg; + Msg.message=msg; + Msg.wParam=wParam; + Msg.lParam=lParam; + Msg.time=0; + EnumThreadWindows(GetCurrentThreadId(),BroadcastMsgCallback,(LPARAM)&Msg); + return Msg.time; +} + +void CMainFrame::SaveAll() +{ + BroadcastMessage(MSG_FORCESAVE,0,0); +} + +void CMainFrame::OpenEditor(const char *name) +{ + if (BroadcastMessage(MSG_FINDANDPOPUP,0,(LPARAM)name)==0) + { + EditSkeldalFile(name); + } +} + +void CMainFrame::OnDestroy() +{ + SaveBarState("MainFrame"); + CFrameWnd::OnDestroy(); + + BroadcastMessage(MSG_CLOSEEDITOR,0,0); + release_list(_adv); + _adv=0; + + +} + +void CMainFrame::StartApp(const char *appname, CString cmdline, bool wait, const char *folder) +{ + SaveAll(); + STARTUPINFO nfo; + memset(&nfo,0,sizeof(nfo)); + nfo.cb=sizeof(nfo); + HANDLE pipe; + if (wait) + { + HANDLE output; + CreatePipe(&pipe,&output,0,0); + DuplicateHandle(GetCurrentProcess(),output,GetCurrentProcess(),&output,0,TRUE,DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE); + nfo.hStdOutput=output; + nfo.hStdError=output; + nfo.dwFlags|=STARTF_USESTDHANDLES; + m_wndView.SetWindowText(""); + } + Pathname app=appname; + cmdline=_T("\"")+CString(appname)+_T("\" ")+cmdline; + CString startdir; + PROCESS_INFORMATION pi; + if (folder==0) + startdir=app.GetDirectoryWithDrive(); + else + startdir=folder; + if (startdir[startdir.GetLength()-1]=='\\') startdir.Delete(startdir.GetLength()-1); + BOOL res=CreateProcess(appname,cmdline.LockBuffer(),0,0,TRUE,NORMAL_PRIORITY_CLASS|DETACHED_PROCESS,0,startdir,&nfo,&pi); + cmdline.UnlockBuffer(); + if (res==FALSE) + { + CString ss; + AfxFormatString1(ss,IDS_CANNOTEXECUTE,cmdline); + AfxMessageBox(ss,MB_ICONSTOP); + } + else + { + CloseHandle(pi.hThread); + if (wait) + { + int rep=10; + bool end; + do + { + DWORD datalen; + PeekNamedPipe(pipe,0,0,0,&datalen,0); + while (datalen) + { + DWORD readed=0; + char buff[256]; + if (ReadFile(pipe,&buff,255,&readed,0)==FALSE) break; + if (readed==0) break; + int cnt=m_wndView.GetWindowTextLength(); + if (cnt>20000) + { + m_wndView.SetSel(0,10000); + m_wndView.ReplaceSel(""); + cnt=m_wndView.GetWindowTextLength(); + } + buff[readed]=0; + kamenik2windows(buff,readed,buff); + m_wndView.SetSel(cnt,cnt); + m_wndView.ReplaceSel(buff); + PeekNamedPipe(pipe,0,0,0,&datalen,0); + rep=10; + } + UpdateWindow(); + end=WaitForSingleObject(pi.hProcess,200)==WAIT_TIMEOUT; + rep--; + } + while (rep>0 || end); + } + CloseHandle(pi.hProcess); + } + if (wait) + { + CloseHandle(pipe); + CloseHandle(nfo.hStdOutput); + } + SetForegroundWindow(); +} + +void CMainFrame::OnPekladaePelokouzla() +{ + CString cmdline=_T("\"")+_baseMapPath+_T("KOUZLA.TAB")+_T("\""); + Pathname apppath=Pathname::GetExePath(); + CString appname=apppath.GetDirectoryWithDrive()+CString(_T("AdvManData\\CSPELLS.EXE")); + StartApp(appname,cmdline,true,_baseMapPath); +} + +void CMainFrame::OnPekladaePelodialogy() +{ + CString cmdline=_T("\"")+_baseMapPath+_T("DIALOGY.DLG")+_T("\""); + Pathname apppath=Pathname::GetExePath(); + CString appname=apppath.GetDirectoryWithDrive()+CString(_T("AdvManData\\CDIALOGY.EXE")); + StartApp(appname,cmdline,true,_baseMapPath); + +} + +void CMainFrame::OnPekladaePelopostavytab() +{ + CString cmdline=_T("\"")+_baseMapPath+_T("POSTAVY.TAB\" \"")+_baseMapPath+_T("POSTAVY.DAT")+_T("\""); + Pathname apppath=Pathname::GetExePath(); + CString appname=apppath.GetDirectoryWithDrive()+CString(_T("AdvManData\\Lex_Lib.exe")); + StartApp(appname,cmdline,true,_baseMapPath); + +} + +void CMainFrame::OnNstrojeMapedit() +{ + Pathname apppath=Pathname::GetExePath(); + apppath.SetFilename(_T("MapEdit.exe")); + StartApp(apppath,CString(_T("\""))+_advName+_T("\""),false); +} + +void CMainFrame::OnNstrojeTestujdobrodrustv() +{ + Pathname apppath=Pathname::GetExePath(); + apppath.SetFilename(_T("Skeldal.exe")); + StartApp(apppath,CString(_T("\""))+_advName+_T("\""),false); +} + +void CMainFrame::OnNstrojeTvrcepodlah() +{ + Pathname apppath=Pathname::GetExePath(); + apppath.SetFilename(_T("AdvManData\\Podlahar.exe")); + StartApp(apppath,"",false,_advPath+get_text_field(_adv,"CESTA_GRAFIKA")); + +} + +void CMainFrame::OnNstrojeTvrcepaletpronestvry() +{ + Pathname apppath=Pathname::GetExePath(); + apppath.SetFilename(_T("AdvManData\\ColEdit.exe")); + StartApp(apppath,"",false,_advPath+get_text_field(_adv,"CESTA_ENEMY")); +} + + +void CMainFrame::OnNstrojeTvrceikonpropedmty() +{ + Pathname apppath=Pathname::GetExePath(); + apppath.SetFilename(_T("AdvManData\\ItemIcons.exe")); + StartApp(apppath,"",false,_advPath+get_text_field(_adv,"CESTA_ITEMY")); +} + +void CMainFrame::OnEditorySouboradv() +{ + AfxMessageBox(IDS_EDITADVWARN,MB_ICONEXCLAMATION); + OpenEditor(_advName); +} + +void CMainFrame::OnFileZnovunast() +{ + release_list(_adv); + _adv=read_config(_advName); + _baseMapPath=_advPath+get_text_field(_adv,"CESTA_MAPY"); +} + +void CMainFrame::OnUpdateFileZnovunast(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(_adv!=0); +} + +void CMainFrame::OnEditoryDialogy() +{ + DlgDialogy dlg; + dlg._dlgpath.SetDirectory(_baseMapPath); + dlg._dlgpath.SetFilename(_T("Dialogy.dlg")); + dlg.DoModal(); +} + +void CMainFrame::OnUpdateEditory(CCmdUI *pCmdUI) +{ + pCmdUI->Enable(_adv!=0); +} diff --git a/AdvMan/MainFrm.h b/AdvMan/MainFrm.h new file mode 100644 index 0000000..5a31502 --- /dev/null +++ b/AdvMan/MainFrm.h @@ -0,0 +1,95 @@ +// MainFrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_MAINFRM_H__0420AD88_2B58_4379_BD0D_069A821C039D__INCLUDED_) +#define AFX_MAINFRM_H__0420AD88_2B58_4379_BD0D_069A821C039D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ChildView.h" + + +class CMainFrame : public CFrameWnd +{ + +public: + CMainFrame(); +protected: + DECLARE_DYNAMIC(CMainFrame) + +// Attributes +public: + TSTR_LIST _adv; + CString _baseMapPath; + CString _advPath; + CString _advName; +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + void StartApp(const char *appname, CString cmdline, bool wait, const char *folder=0); + void OpenEditor(const char *name); + void SaveAll(); + static LRESULT BroadcastMessage(UINT msg, WPARAM wParam, LPARAM lParam); + void SetTitle(const _TCHAR *name); + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + CToolBar m_wndEditoryBar; + CToolBar m_wndPrekladaceBar; + CEdit m_wndView; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSetFocus(CWnd *pOldWnd); + afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu); + afx_msg void OnFileNovdobrodrust(); + afx_msg void OnFileNatidobrodrustv(); + afx_msg void OnEditoryKouzlatab(); + afx_msg void OnEditoryPostavytab(); + afx_msg void OnEditoryItemsscr(); + afx_msg void OnEditoryItemspic(); + afx_msg void OnEditoryWeaponsscr(); + afx_msg void OnDestroy(); + afx_msg void OnPekladaePelokouzla(); + afx_msg void OnPekladaePelodialogy(); + afx_msg void OnPekladaePelopostavytab(); + afx_msg void OnNstrojeMapedit(); + afx_msg void OnNstrojeTestujdobrodrustv(); + afx_msg void OnNstrojeTvrcepodlah(); + afx_msg void OnNstrojeTvrcepaletpronestvry(); + afx_msg void OnNstrojeTvrceikonpropedmty(); + afx_msg void OnEditorySouboradv(); + afx_msg void OnFileZnovunast(); + afx_msg void OnUpdateFileZnovunast(CCmdUI* pCmdUI); + afx_msg void OnEditoryDialogy(); + afx_msg void OnUpdateEditory(CCmdUI *pCmdUI); +//}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__0420AD88_2B58_4379_BD0D_069A821C039D__INCLUDED_) diff --git a/AdvMan/Pathname.cpp b/AdvMan/Pathname.cpp new file mode 100644 index 0000000..aa14710 --- /dev/null +++ b/AdvMan/Pathname.cpp @@ -0,0 +1,621 @@ +// Pathname.cpp: implementation of the Pathname class. +// +////////////////////////////////////////////////////////////////////// + +#include "Pathname.h" +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +#pragma comment(lib,"User32") +#pragma comment(lib,"shell32") + +Pathname::Pathname(const char *name) +{ + _fullpath=NULL; + _path=_filetitle=_extension=_end=""; + + if (name==NULL) SetPathName("*.*"); + else SetPathName(name); +} + +Pathname::Pathname(PathNameNullEnum null) +{ + _fullpath=NULL; + _path=_filetitle=_extension=_end=""; +} + + +Pathname::Pathname(const char *relpath, const Pathname &abspath) +{ + _path=_filetitle=_extension=_end=""; + _fullpath=NULL; + + char *part; + char *pth=strcpy((char *)alloca(sizeof(*relpath)+strlen(relpath)+1),relpath); + part=strrchr(pth,'\\'); + if (part) part++;else part=NULL; + if (part) + { + SetFilename(part); + *part=0; + SetDirectory(pth); + } + else + SetFilename(pth); + if (RelativeToFull(abspath)==false) SetNull(); +} + + +Pathname::~Pathname() +{ + delete [] _fullpath; +} + +const char *Pathname::GetNameFromPath(const char *path) +{ + char *c=strrchr(path,'\\'); + if (c!=NULL) c++;else return path; + return c; +} + +const char *Pathname::GetExtensionFromPath(const char *path) +{ + const char *fname=GetNameFromPath(path); + char *c=strrchr(fname,'.'); + if (c==NULL) c=strrchr(path,0); + return c; +} + +void Pathname::RebuildData(const char *path, const char *filetitle, const char *extension, int pathlen, int titlelen, int extlen) +{ + int totalsize=(pathlen+titlelen+extlen)*2+10; + char *olddata=_fullpath; + _fullpath=new char[totalsize]; + _path=_fullpath+pathlen+titlelen+extlen+1; + memcpy(_path,path,pathlen+1); + _filetitle=_path+pathlen+1; + memcpy(_filetitle,filetitle,titlelen+1); + _extension=_filetitle+titlelen+1; + memcpy(_extension,extension,extlen+1); + _end=_extension+extlen+1; + RebuildPath(); + delete [] olddata; +} + +void Pathname::RebuildPath() +{ + sprintf(_fullpath,"%s%s%s",_path,_filetitle,_extension); +} + +void Pathname::SetDrive(const char dr) +{ + if (HasDrive()) + { + if (dr==0) + { + strcpy(_path,_path+2); + strcpy(_fullpath,_fullpath+2); + } + else + { + _path[0]=dr; + _fullpath[0]=dr; + } + } + else if (dr!=0) + { + int np=IsNetworkPath(); + if (np) + { + _path[0]=dr; + _path[1]=':'; + strcpy(_path+2,_path+np); + RebuildPath(); + } + else + { + char *c=(char *)alloca((strlen(_path)+4)*sizeof(*c)); + sprintf(c,"%c:%s",dr,_path); + SetDirectory(c); + } + } +} + +void Pathname::SetDirectory(const char *dir) +{ + bool copydrv; //directory doesn't contain drive, need copy from original + bool addslash; //directory doesn't ending by backslash, need add it + + int len=strlen(dir); + copydrv=HasDrive() && !HasDrive(dir); //copy original drive, if exists and directory doesn't contaion drive + if (strncmp(dir,"\\\\",2)==0) copydrv=false; //network path, don't copy drive + addslash=len && dir[len-1]!='\\'; //add slash + if (addslash || copydrv) + { + char *c=(char *)alloca((len+4)*sizeof(dir[0])); //allocate some space for string + if (addslash && copydrv) + sprintf(c,"%c%c%s\\",_path[0],_path[1],dir); //add drive and add slash + else if (addslash) + sprintf(c,"%s\\",dir); //add slash only + else + sprintf(c,"%c%c%s",_path[0],_path[1],dir); //add drive only + dir=c; //this is new path for now + len=strlen(dir); + } + if (len<_filetitle-_path) //there is space for store path + {strcpy(_path,dir); RebuildPath();} //store it and rebuild result + else + RebuildData(dir,_filetitle,_extension,len,strlen(_filetitle),strlen(_extension)); + //rebuild internal data complettly +} + +void Pathname::SetFilename(const char *filename) +{ + char *dot=strrchr(filename,'.'); + if (dot==NULL) + { + SetFiletitle(filename); + SetExtension(""); + return; + } + int tllen=dot-filename; + int exlen=strlen(dot); + char *c=(char *)alloca((tllen+1)*sizeof(*c)); + memcpy(c,filename,tllen); + c[tllen]=0; + if (exlen+tllen+1<_end-_filetitle) + { + memcpy(_filetitle,c,tllen+1); + _extension=_filetitle+tllen+1; + memcpy(_extension,dot,exlen+1); + RebuildPath(); + } + else + RebuildData(_path,c,dot,strlen(_path),tllen,exlen); +} + +void Pathname::SetExtension(const char *ext) +{ + int len=strlen(ext); + if (ext[0] && ext[0]!='.') + { + char *s=(char *)alloca((len+2)*sizeof(*s)); + sprintf(s,".%s",ext); + ext=s; + len++; + } + if (len<_end-_extension) + { + memcpy(_extension,ext,len+1); + RebuildPath(); + } + else + { + RebuildData(_path,_filetitle,ext,strlen(_path),strlen(_filetitle),len); + } +} + +void Pathname::SetFiletitle(const char *title) +{ + int len=strlen(title); + if (len<_extension-_filetitle) + { + memcpy(_filetitle,title,len+1); + RebuildPath(); + } + else + { + RebuildData(_path,title,_extension,strlen(_path),len,strlen(_extension)); + } +} + +void Pathname::SetPathName(const char *pathname) +{ + if (pathname==NULL || pathname[0]==0) + { + SetNull(); + return; + } + char *part; + DWORD needsz=GetFullPathName(pathname,0,NULL,&part); + char *fpth=(char *)alloca(needsz*sizeof(*fpth)); + GetFullPathName(pathname,needsz,fpth,&part); + part=strrchr(fpth,'\\'); + if (part) part++;else part=NULL; + if (part) + { + SetFilename(part); + *part=0; + } + else + SetFilename(""); + SetDirectory(fpth); +} + +Pathname& Pathname::operator=(const Pathname& other) +{ + if (other.IsNull()) SetNull(); + else RebuildData(other._path,other._filetitle,other._extension,strlen(other._path),strlen(other._filetitle),strlen(other._extension)); + return *this; +} + +Pathname::Pathname(const Pathname &other) +{ + _fullpath=NULL; + if (other.IsNull()) SetNull(); + else RebuildData(other._path,other._filetitle,other._extension,strlen(other._path),strlen(other._filetitle),strlen(other._extension)); +} + +bool Pathname::FullToRelative(const Pathname &relativeto) +{ + if (relativeto.IsNull() || IsNull()) return false; + bool h1=HasDrive(); + bool h2=relativeto.HasDrive(); + if (h1!=h2) return false; //rozdilny zpusob adresace - nelze vytvorit relatvni cestu + if (h1==true && h2==true && toupper(GetDrive())!=toupper(relativeto.GetDrive())) + return false; //ruzne disky, nelze vytvorit relativni cestu + if (strncmp(_path,"\\\\",2)==0) //sitova cesta + { + int slsh=0; //citac lomitek + const char *a=_path; + const char *b=relativeto._path; + while (toupper(*a)==toupper(*b) && *a && slsh<3) //zacatek sitove cesty musi byt stejny + { + if (*a=='\\') slsh++; + a++;b++; + } + if (slsh!=3) return false; //pokud neni stejny, nelze vytvorit relativni cestu + } + int sublevel=0; + const char *ps1=_path; + const char *ps2=relativeto._path; + if (h1) + {ps1+=2;ps2+=2;} + const char *sls=ps2; + while (toupper(*ps1)==toupper(*ps2) && *ps1) + { + if (*ps2=='\\') sls=ps2+1; + ps1++;ps2++; + } + ps1-=ps2-sls; + if (sls) + { + while (sls=strchr(sls,'\\')) + { + sls++; + sublevel++; + } + } + char *buff=(char *)alloca((sublevel*3+strlen(ps1)+1)*sizeof(*buff)); + char *pos=buff; + for (int i=0;iref._path) + { + end--; + while (end>ref._path && end[-1]!='\\') end--; + } + beg+=3; + } + else + beg+=2; + } + int partln=end-ref._path; + char *buff=(char *)alloca((partln+strlen(beg)+1)*sizeof(*buff)); + memcpy(buff,ref._path,partln); + strcpy(buff+partln,beg); + SetDrive(0); + SetDirectory(buff); + return true; +} + +int Pathname::IsNetworkPath() const +{ + if (strncmp(_path,"\\\\",2)==0) //sitova cesta + { + const char *p=_path+2; + char *c=strchr(p,'\\'); + if (c) return c-_path; + } + return 0; +} + +void Pathname::SetServerName(const char *server) +{ + if (HasDrive()) SetDrive(0); + else + { + int np=IsNetworkPath(); + if (np) strcpy(_path,_path+np); //str + } + char *buff=(char *)alloca((strlen(server)+strlen(_path)+5)*sizeof(*buff)); + if (_path[0]!='\\') + sprintf(buff,"\\\\%s\\%s",server,_path); + else + sprintf(buff,"\\\\%s%s",server,_path); + SetDirectory(buff); +} + +void Pathname::SetNull() +{ + delete [] _fullpath; + _fullpath=NULL; + _path=_filetitle=_extension=_end=""; +} + +bool Pathname::GetPartFromPath(const char *path, int partnum, char *buff, int bufsize, int mode) +{ + const char *scan=path; + while (*scan=='\\') scan++; + while (partnum && *scan) + { + while (*scan!='\\' && *scan) scan++; + while (*scan=='\\') scan++; + partnum--; + } + if (*scan==0) + { + buff[0]=0; + return false; + } + int pt=0; + if (mode==-1) + { + pt=scan-path; + if (pt>bufsize) + { + buff[0]=0; + return true; + } + else + memcpy(buff,path,pt); + } + bool nlast=false; + while (*scan && (mode==1 || !nlast) && ptsize) return false; + if (psize==0) {buff[0]=0;return true;} + strncpy(buff,GetDirectoryWithDrive(),psize-1); + buff[psize-1]=0; + return true; +} + +bool Pathname::IsPathValid() const +{ + if (IsNull()) return false; + char *invalidChars="/*?\"<>|"; + const char *path=GetFullPath(); + if (*path==0) return false; + while (*path) + { + if (strchr(invalidChars,*path)!=NULL) return false; + path++; + } + return true; +} + + + +bool Pathname::SetTempDirectory() +{ + char buff[1]; + DWORD size=GetTempPath(1,buff); + if (size==0) return false; + size++; + char *p=(char *)alloca(size); + if (GetTempPath(size,p)==0) return false; + SetDirectory(p); + return true; +} + +bool Pathname::SetDirectorySpecial(int nSpecCode) +{ + char buff[MAX_PATH]; + if (SHGetSpecialFolderPath(GetForegroundWindow(),buff,nSpecCode,FALSE)!=NOERROR) return false; + SetDirectory(buff); + return true; +} + +bool Pathname::SetTempFile(const char *prefix, unsigned int unique) +{ + char tempname[MAX_PATH]; + if (GetTempFileName(GetDirectoryWithDrive(),prefix,unique,tempname)==0) return false; + this->SetPathName(tempname); + return true; +} + +Pathname Pathname::GetExePath() +{ + char buff[MAX_PATH*4]; + GetModuleFileName(NULL,buff,sizeof(buff)); + return Pathname(buff); +} + +const char *Pathname::FullToRelativeProjectRoot(const char *full, const char *projectRoot) +{ + const char *a=full,*b=projectRoot; + while (*a && tolower(*a)==tolower(*b)) {a++;b++;}; + if (*b) return full; + return a; +} + +bool Pathname::CreateFolder(void *security_descriptor) +{ + int begpart=-1; + int len=strlen(_fullpath)+1; + char *buff=(char *)alloca(len); + for (int i=1;GetPart(i,buff,len,-1);i++) + { + if (begpart==-1 && _access(buff,0)!=0) begpart=i; + if (begpart!=-1) + { + if (begpart==-1) begpart=i; + BOOL res=CreateDirectory(buff,(LPSECURITY_ATTRIBUTES)security_descriptor); + if (res==FALSE) + { + for (int j=i;i>=begpart;i--) + { + GetPart(i,buff,len,-1); + RemoveDirectory(buff); + } + return false; + } + } + } + return true; +} + +bool Pathname::CreateFolder(const char *path, void *security_descriptor) +{ + Pathname pth; + pth.SetDirectory(path); + return pth.CreateFolder(security_descriptor); +} + +static bool RemoveDirectoryFull(const Pathname &p, int part, char *buff, int bufsize) +{ + if (p.GetPart(part+1,buff,bufsize,-1)) + if (RemoveDirectoryFull(p,part+1,buff,bufsize)==false) return false; + p.GetPart(part,buff,bufsize, -1); + return RemoveDirectory(buff)!=FALSE; +} + +static bool RemoveDirRecursive(const char *dir, const char *mask) +{ + if (dir==0 || dir[0]==0) return false; + if (strcmp(dir,"\\")==0) return false; + bool res=true; + Pathname newp; + newp.SetDirectory(dir); + if (mask) + { + WIN32_FIND_DATAA fnd; + HANDLE h; + newp.SetFilename(mask); + h=FindFirstFileA(newp,&fnd); + if (h) + { + do + { + if (!(fnd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + newp.SetFilename(fnd.cFileName); + if (DeleteFile(newp)==FALSE) res=false; + } + }while (FindNextFileA(h,&fnd)); + CloseHandle(h); + } + } + { + WIN32_FIND_DATAA fnd; + HANDLE h; + newp.SetFilename("*.*"); + h=FindFirstFileA(newp,&fnd); + if (h) + { + do + { + if ((fnd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(fnd.cFileName,".")!=0 && strcmp(fnd.cFileName,"..")!=0) + { + newp.SetFilename(fnd.cFileName); + if (RemoveDirRecursive(newp,mask)==false) res=false; + else DeleteFile(newp); + } + }while (FindNextFileA(h,&fnd)); + CloseHandle(h); + } + } + return res; + +} + +bool Pathname::DeleteFolder(int dfFlags) +{ + int bufflen=strlen(_fullpath)+1; + char *buff=(char *)alloca(bufflen); +/* if (dfFlags & DFRecycleBin) + { + GetDirectoryWithDriveWLBS(buff,bufflen); + SHFILEOPSTRUCT delinfo; + delinfo.hwnd=NULL; + delinfo.wFunc=FO_DELETE; + delinfo.pFrom=GetFullPath(); + delinfo.pTo=NULL; + delinfo.fFlags=FOF_ALLOWUNDO|FOF_NOCONFIRMATION|FOF_NOERRORUI|((dfFlags & DFRecursive)?0:FOF_NORECURSION)| + ((dfFlags & DFShowProgress)?0:FOF_SILENT); + delinfo.fAnyOperationsAborted=0; + delinfo.hNameMappings=0; + delinfo.lpszProgressTitle=0; + + } + else*/ + { + if (dfFlags & DFRecursive) + { + bool res=RemoveDirRecursive(GetDirectoryWithDrive(),dfFlags & DFFile?GetFilename():0); + if (res==false) return false; + } + if (dfFlags & DFPath) + { + if (GetPart(1,buff,bufflen,-1)==false) return false; + return RemoveDirectoryFull(*this, 1,buff,bufflen); + } + else + { + GetDirectoryWithDriveWLBS(buff,bufflen); + return RemoveDirectory(buff)!=FALSE; + } + + } + return false; +} \ No newline at end of file diff --git a/AdvMan/Pathname.h b/AdvMan/Pathname.h new file mode 100644 index 0000000..8b4c999 --- /dev/null +++ b/AdvMan/Pathname.h @@ -0,0 +1,451 @@ +// Pathname.h: interface for the Pathname class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_Pathname_H__40F41C23_3AA2_486C_B9E5_33AEE67FB313__INCLUDED_) +#define AFX_Pathname_H__40F41C23_3AA2_486C_B9E5_33AEE67FB313__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include +#include + +#ifndef ASSERT +#ifdef _DEBUG +#define ASSERT(x) assert(x) +#else +#define ASSERT(x) +#endif +#endif + +enum PathNameNullEnum {PathNull}; + +#define PathNameCompare(op) bool operator op (const Pathname &other) const \ +{if (IsNull() || other.IsNull()) return false;else return stricmp(_fullpath,other._fullpath) op 0;}\ + bool operator op (const char *other) const \ +{ASSERT(other[0]!=0);\ + if (IsNull() || other==NULL) return false;else return stricmp(_fullpath,other) op 0;} + +#ifndef _UNICODE + +/** class Pathname simplifying manipulation with pathnames, filenames, general paths, and +also supports convert from absolute path to relative respectively */ + + + +class Pathname +{ + ///object value and data + /**The implementation of Pathname creates only one buffer for all variables. It can + increase speed by effective memory use. Strings are stored one after another separated + by zero byte. Evry time any string changed, implementation recalculate buffer usage, and + decide, whether it should resize buffer or not. + + _fullpath also points to string contain full path with filename, + it is dominant value of the class + */ + char *_fullpath; + char *_path; /// + If name is provided, Pathname will expand it into full name with drive and folder name. + @param name optional argument to inicialize object + */ + Pathname(const char *name=NULL); + + ///Construct Pathname class + /** Using this constructor Pathname(PathNull) will create Pathname class with null content is set. + If null content is set, all string-query function returns NULL. IsNull function returns true. This state + is sets until new path is assigned. There is a set of functions invalid called in null state. + */ + + Pathname(PathNameNullEnum null); + + ///Construct Pathname class + /** + @param relpath Relative path or uncomplette path or single filename with extension. + Pathname will expand this pathname into full using absolute path provided by the second + argument. + @param abspath Absolute path used as reference to folder - the origin of relative path + provided in the first argument. + */ + Pathname(const char *relpath, const Pathname &abspath); + + ///Construct Pathname as copy of another pathname + Pathname(const Pathname &other); + + ///Destruct Pathname + virtual ~Pathname(); + + ///Function returns the current drive letter. + /** Before usage, ensure, that current pathname contain drive. + In network path drive letter is missing. + In this case, result is undefined. To ensure, use HasDrive function + @return the drive letter of current path. + */ + char GetDrive() const + { + if (IsNull()) return 0; + return _path[0]; + } + + ///Static function determines, if argument contain a drive information. + /** + @param dir directory to inspect + @return true, if directory contain drive.

+ This function is independed, it don't need any Pathname variable declared. + */ + static bool HasDrive(const char *dir) + {return (isalpha(dir[0]) && dir[1]==':');} + + ///Function determines, if current pathname contain a drive information + /** + @return true, if current pathname contain a drive information + */ + bool HasDrive() const + { + if (IsNull()) return false; + return HasDrive(_path); + } + + + ///Function returns current folder name + /** + if current folder name contain drive, only folder name is returned (without drive). + In other cases (relative or network drives) returns full path. + @return folder name or full path. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const char *GetDirectory() const + { + if (HasDrive()) return _path+3; + else return _path; + } + + const char *GetDirectoryWithDrive() const + { + return _path; + } + + ///Function returns current filename with extension + /** + @return current filename with extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const char *GetFilename() const + { + if (IsNull()) return NULL; + const char *blk=strrchr(_fullpath,'\\'); + if (blk) blk=blk+1;else blk=_fullpath; + return blk; + } + + ///Function returns current extension (with starting dot) + /** + @return current extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const char *GetExtension() const + {return _extension;} + + ///Function returns current filename without extension (without dot) + /** + @return current filename without extension (without dot). Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const char *GetTitle() const + {return _filetitle;} + + ///Function changes current drive. + /**If object contain pathname with drive, then current drive is changed and function returns. + If object contain network path, then computer name is changed to the drive name. + If object contain relative path, then whole path is replaced by path on root on drive. + @param dr new drive letter. This parameter can be set to zero. It means, that current + driver is deleted, and path is converted to relative path from root. Note: Zero c + cannot be used with network paths and relative paths, and finnaly has no effect to the object + */ + + void SetDrive(const char dr); + + ///Sets new directory for object + /** if object contain a drive letter and argument dir doesn't, then current drive is remain + and only directory part is replaced. If current path is network path or relative path, + then whole path is replaced by new one. + If argument dir contain drive letter, then whole path is replaced too. + @param dir contain new pathname. Backslash should be the last character in string + */ + void SetDirectory(const char *dir); + + ///Sets new filename for object. + /** + If filename contain dot, function assumes, that filename is provided with extension. + Otherwise, current extension remains untouched. + @param filename new filename for object + */ + + void SetFilename(const char *filename); + + ///Sets new extension for object. + /** + If ext doesn't starting with dot, function adds it. + @param ext new extension for object + */ + void SetExtension(const char *ext); + + ///Sets new file title + /** Function changes file title, extension remains untouched. + if title contains extension (dot inside its name), this extension doesn't change + current extension. For example, if current extension is ".cpp" and filetitle contain + "source.h", then result is "source.h.cpp" + @param title a new title for object. + */ + + void SetFiletitle(const char *title); + + ///Function returns full pathname. + /** + @return current pathname. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + + const char *GetFullPath() const + {return _fullpath;} + + ///Sets pathname + /** Function has same effect as constructor. But it can be used + anytime during object lifetime. It simply replaces current pathname with newer. Pathname + in argument is expanded to full pathname, current directory is used as reference. + @param pathname new pathname + */ + void SetPathName(const char *pathname); + + Pathname& operator=(const char *other) + {SetPathName(other);return *this;} + Pathname& operator=(const Pathname& other); + + ///converts object to string + operator const char *() const + {return GetFullPath();} + + ///Static function to help getting filename from pathname + /** Function finds last backslash / and return pointer to first character after it. + Pointer stays valid until original path is destroyed or until original path is changed + @param path pathname to inspect as string + @return pointer to filename + */ + static const char *GetNameFromPath(const char *path); + + ///Static function to help getting extension from pathname + /** Function finds last dot '.' in filename return pointer to it (extension with dot). + Pointer stays valid until original path is destroyed or until original path is changed + @param path pathname to inspect as string + @return pointer to extension + */ + static const char *GetExtensionFromPath(const char *path); + + ///Function sets server name for network path + /** If current path is network path, then changes server name to newer. Otherwise + it remove drive letter, and insert server name before remain path + @param server server name without slashes + */ + void SetServerName(const char *server); + + ///Function inspects current path and returns, whether contain server name + /**@return zero, if current path is not valid network path. Nonzero if path contain + server name. Then value returned count characters containing server name with precedent + slashes. + */ + int IsNetworkPath() const; + + ///Function converts current relative path into absolute path + /** + If current path is not relative, function do nothing. + @param ref reference to path, against which path is relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool RelativeToFull(const Pathname &ref); + + ///Function converts current absolute path into relative path + /** + If current path is not relative, function do nothing. Both paths must be on the same + drive or network computer. + + @param ref reference to path, against which path should be relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool FullToRelative(const Pathname &relativeto); + + Pathname& operator+=(const char *relativePath) + {*this=Pathname(relativePath,*this);return *this;} + + Pathname operator+(const char *relativePath) + {Pathname out(relativePath,*this);return out;} + + bool IsNull() const {return _fullpath==NULL;} + + void SetNull(); + + PathNameCompare(<) + PathNameCompare(>) + PathNameCompare(==) + PathNameCompare(>=) + PathNameCompare(<=) + PathNameCompare(!=) + + + ///Function gets part of pathname + /** + @param path subject of examine + @param partnum zero-base index of part of pathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count characters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + static bool GetPartFromPath(const char *path, int partnum, char *buff, int bufsize, int mode=0); + + ///Function gets part of object + /** + @param partnum zero-base index of part of pathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count characters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + bool GetPart(int partnum, char *buff, int bufsize,int mode=0) const + { + return GetPartFromPath(this->_fullpath,partnum,buff,bufsize,mode); + } + + /// Get Directory With Drive Without Last Back Slash + /** Retrieves into buffer directory with drive and removes last backslash + @param buff buffer that retrieves path + @param size size of buffer + @return true, if success, failed if buffer is too small*/ + + + bool GetDirectoryWithDriveWLBS(char *buff, size_t size) const; + + + /// function checks, if path is valid and returns true, if does. + bool IsPathValid() const; + + /// Sets special directory. + /** + @param bSpecCode this value may be operation-system + depend. Windows implementation using CSIDL_XXXX constants, which is described in SHGetSpecialFolderLocation function + description + @return true, if function were successful + */ + bool SetDirectorySpecial(int nSpecCode); + + ///Sets temporaly directory. + bool SetTempDirectory(); + + ///Guess temporaly file name + /** + @param prefix prefix string for name + @param unique if unique is non-zero, it is used for new temporaly file. If unique is zero, function guess own unique + value. + @return true if function were successful + */ + bool SetTempFile(const char *prefix="tmp", unsigned int unique=NULL); + + ///Returns path of current executable. + /**It useful, when accessing folder, from when current module has been executed */ + static Pathname GetExePath(); + + ///Solves most used conversion from fullpath to path relative to project root + /** + @param full full pathname with drive + @param projectRoot project root path + @return function returns pointer to full path, where starts relative part. If + fullpath doesn't contain project root path, it returns pointer to full. + @example FullToProjectRoot("x:\\project\\data\\example.txt","x:\\project"); //result is "data\\example.txt" + */ + + static const char *FullToRelativeProjectRoot(const char *full, const char *projectRoot); + + ///Creates folder from path + static bool CreateFolder(const char *path, void *security_descriptor=0); + + ///Creates all folders from path stored in object + /** + Function creates path stored in object. Function creates whole path, when it doesn't + exists. + @param security_descriptor pointer for additional information about security on new folder + if this parameter is NULL, default descriptor is used. This parameter is platform + depended. + @return if path has been created, returns true. In case of error, returns false + and no changes are made on disk (Function rollbacks any changes) + */ + bool CreateFolder(void *security_descriptor=0); + + + enum DeleteFolderFlags { + DFSimple=0, //only deletes latest folder + DFPath=1, //deletes whole path, if there are no files + DFFile=2, //deletes file specified in object. You can use wildcards + DFRecursive=4, //also deletes all folders inside the path +/* DFRecycleBin=8, //move all deleted files or folders into recycle bin + DFShowProgress=16, //enables progress bar during deleting*/ + }; + + ///Deletes folder stored in object + /** + @param dfFlags combination of flags. + @return function returns true, when no error occured. Function return false, + when error occured. + */ + bool DeleteFolder(int dfFlags); + + +protected: + ///Function rebuild buffer with new values + /** This protected function recalculates space for buffer, allocated it, and rebuild its + content with data supplied by arguments. Function doesn't assumes, that all strings are + terminated by zero by default. "pathlen, titlelen and extlen" must contain correct values. + Terminating zero is not included, but function excepting it. + Valid using is: RebuildData(a,b,c,strlen(a),strlen(b),strlen(c)); + All pointers returned by Get functions can be used and stays valid, until this function returns. + */ + void RebuildData(const char *path, const char *filetitle, const char *extension, int pathlen, int titlelen, int extlen); + ///Function only rebuild _fullpath string. + /** It doesn't check space for string! This function is used, when length of path is excepted + the same or smaller, then current. + */ + void RebuildPath(); + + +}; + + +#else + +#error unicode version of Pathname is not currently supported + +#endif + +#undef PathNameCompare + +#endif // !defined(AFX_Pathname_H__40F41C23_3AA2_486C_B9E5_33AEE67FB313__INCLUDED_) diff --git a/AdvMan/StdAfx.cpp b/AdvMan/StdAfx.cpp new file mode 100644 index 0000000..46c628d --- /dev/null +++ b/AdvMan/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// AdvMan.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/AdvMan/StdAfx.h b/AdvMan/StdAfx.h new file mode 100644 index 0000000..c87af4f --- /dev/null +++ b/AdvMan/StdAfx.h @@ -0,0 +1,33 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__978B5377_B3F7_4A88_A4CA_02390EC070E2__INCLUDED_) +#define AFX_STDAFX_H__978B5377_B3F7_4A88_A4CA_02390EC070E2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +extern "C" +{ +#include +#include +} +#include "Pathname.h" +#include +#include "..\mapedit\editor.h" +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__978B5377_B3F7_4A88_A4CA_02390EC070E2__INCLUDED_) diff --git a/AdvMan/bgraph2dx.h b/AdvMan/bgraph2dx.h new file mode 100644 index 0000000..e69de29 diff --git a/AdvMan/debug.h b/AdvMan/debug.h new file mode 100644 index 0000000..e69de29 diff --git a/AdvMan/idc_note.ico b/AdvMan/idc_note.ico new file mode 100644 index 0000000..c6dc4fe Binary files /dev/null and b/AdvMan/idc_note.ico differ diff --git a/AdvMan/mem.h b/AdvMan/mem.h new file mode 100644 index 0000000..02ee3d7 --- /dev/null +++ b/AdvMan/mem.h @@ -0,0 +1,4 @@ +__inline void *getmem(long sz) +{ + return malloc(sz); +} \ No newline at end of file diff --git a/AdvMan/res/AdvMan.ico b/AdvMan/res/AdvMan.ico new file mode 100644 index 0000000..5311fc7 Binary files /dev/null and b/AdvMan/res/AdvMan.ico differ diff --git a/AdvMan/res/AdvMan.rc2 b/AdvMan/res/AdvMan.rc2 new file mode 100644 index 0000000..cb2e42e --- /dev/null +++ b/AdvMan/res/AdvMan.rc2 @@ -0,0 +1,13 @@ +// +// ADVMAN.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/AdvMan/res/Toolbar.bmp b/AdvMan/res/Toolbar.bmp new file mode 100644 index 0000000..90aadbe Binary files /dev/null and b/AdvMan/res/Toolbar.bmp differ diff --git a/AdvMan/res/editory.bmp b/AdvMan/res/editory.bmp new file mode 100644 index 0000000..c4aeb87 Binary files /dev/null and b/AdvMan/res/editory.bmp differ diff --git a/AdvMan/res/prekladace.bmp b/AdvMan/res/prekladace.bmp new file mode 100644 index 0000000..5493fd2 Binary files /dev/null and b/AdvMan/res/prekladace.bmp differ diff --git a/AdvMan/resource.h b/AdvMan/resource.h new file mode 100644 index 0000000..009d8cc --- /dev/null +++ b/AdvMan/resource.h @@ -0,0 +1,88 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by AdvMan.rc +// +#define IDC_ADD 4 +#define IDC_DELETE 5 +#define IDC_RESCAN 6 +#define IDD_ABOUTBOX 101 +#define IDD_TEXTEDITOR 105 +#define IDR_EDITORMENU 107 +#define IDI_MAINICON 117 +#define IDI_NOTEPADICON 118 +#define IDR_MAINFRAME 128 +#define IDR_ADVMANTYPE 129 +#define IDS_NOVEDOBRODRUZSTVIDOKONCENO 129 +#define IDD_NOVEDOBR 130 +#define IDS_ADVFILTER 130 +#define IDS_CHYBAPRICTENI 131 +#define IDS_MAINFRAMETITLE 132 +#define IDS_UNTITLED 133 +#define IDS_CANNOTEXECUTE 134 +#define IDD_DIALOGY 134 +#define IDS_NEMOHUNAJITNICOD 135 +#define IDD_NOVYDIALOG 135 +#define IDS_EDITADVWARN 136 +#define IDR_TOOLEDITORY 136 +#define IDS_DLGNAME 137 +#define IDS_DLGDESC 138 +#define IDR_PREKLADACE 138 +#define IDS_DLGID 139 +#define IDS_UNABLETOSAVEDIALOGYDLG 140 +#define IDS_NODESC 141 +#define IDC_JMENO 1000 +#define IDC_EDIT 1000 +#define IDC_ORGANIZACE 1001 +#define IDC_RADIO2 1002 +#define IDC_RADIO3 1003 +#define IDC_KOUZLA 1004 +#define IDC_DIALOGY 1005 +#define IDC_DEFINICE 1006 +#define IDC_MAPY 1007 +#define IDC_MAPY2 1008 +#define IDC_ORIGDLGS 1008 +#define IDC_STARTMAP 1009 +#define IDC_MINPOSTAV 1010 +#define IDC_MAXPOSTAV 1011 +#define IDC_DLGLIST 1012 +#define IDC_POPIS 1013 +#define IDC_CISLO 1016 +#define ID_FILE_NOVDOBRODRUST 32771 +#define ID_FILE_NATIDOBRODRUSTV 32773 +#define ID_EDITORY_KOUZLATAB 32774 +#define ID_EDITORY_POSTAVYTAB 32775 +#define ID_EDITORY_DIALOGY 32776 +#define ID_EDITORY_ITEMSSCR 32777 +#define ID_EDITORY_ITEMSPIC 32778 +#define ID_EDITORY_WEAPONSSCR 32779 +#define ID_NSTROJE_TVRCEPODLAH 32780 +#define ID_NSTROJE_TVRCEPALETPRONESTVRY 32781 +#define ID_NSTROJE_TVRCEIKONPROPEDMTY 32782 +#define ID_PEKLADAE_PELOKOUZLA 32783 +#define ID_PEKLADAE_PELODIALOGY 32784 +#define ID_PEKLADAE_PELOPOSTAVYTAB 32785 +#define ID_NSTROJE_EXPORTUJDOBRODRUSTV 32786 +#define ID_NSTROJE_TEKADDLSOUBOR 32787 +#define ID_NSTROJE_MAPEDIT 32788 +#define ID_NSTROJE_TESTUJDOBRODRUSTV 32789 +#define ID_EDITORY_SOUBORADV 32790 +#define ID_FILE_ZNOVUNAST 32791 +#define ID_VIEW_PREKLADACE 32802 +#define ID_VIEW_EDITORY 32810 +#define ID_PRAVY_UNDO 40001 +#define ID_UPRAVY_COPY 40002 +#define ID_UPRAVY_VYJMOUT 40003 +#define ID_UPRAVY_VLOZIT 40004 +#define ID_UPRAVY_VYMAZAT 40005 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 140 +#define _APS_NEXT_COMMAND_VALUE 32815 +#define _APS_NEXT_CONTROL_VALUE 1018 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/AdvMan/skeldal_win.h b/AdvMan/skeldal_win.h new file mode 100644 index 0000000..4fa48b5 --- /dev/null +++ b/AdvMan/skeldal_win.h @@ -0,0 +1,4 @@ +#include +#include +#include +#include \ No newline at end of file diff --git a/DDLReader/DDLFile.cpp b/DDLReader/DDLFile.cpp new file mode 100644 index 0000000..9f5b556 --- /dev/null +++ b/DDLReader/DDLFile.cpp @@ -0,0 +1,93 @@ +#include "stdafx.h" +#include ".\ddlfile.h" + +DDLFile::DDLFile(void) +{ + _hFile=0; +} + +DDLFile::~DDLFile(void) +{ + if (_hFile!=0) CloseHandle(_hFile); +} + + + + +bool DDLFile::OpenDDLFile(WString filename) +{ + _hFile=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, + OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL); + if (_hFile==INVALID_HANDLE_VALUE) + { + _hFile=0; + return false; + } + return true; +} + +bool DDLFile::ReadFile(void *data, size_t sz) +{ + DWORD readed=0; + if (::ReadFile(_hFile,data,sz,&readed,NULL)==FALSE) return false; + if (readed!=sz) return false; + return true; +} + +bool DDLFile::EnumFiles(IDDLFileEnumerator &enmClass) +{ + unsigned long firstGroup; + unsigned long groupEndOffset; + unsigned long endGroups; + int i; + int ngroups; + SetFilePointer(_hFile,0,0,FILE_BEGIN); + if (ReadFile(&firstGroup,sizeof(firstGroup))==false) return false; + if (ReadFile(&groupEndOffset,sizeof(firstGroup))==false) return false; + unsigned long *group=(unsigned long *)alloca(groupEndOffset); + group[0]=firstGroup; + group[1]=groupEndOffset; + ngroups=groupEndOffset/8; + if (groupEndOffset!=8 && ReadFile(group+2,groupEndOffset-8)==false) return false; + SetFilePointer(_hFile,12,0,FILE_CURRENT); + if (ReadFile(&endGroups,sizeof(endGroups))==false) return false; + for (i=0;i(other); + dother.data=0;dother.sz=0; + } + DDLData& operator =(const DDLData &other) + { + DDLData &dother=const_cast(other); + data=other.data;sz=other.sz; + dother.data=0;dother.sz=0; + return *this; + } +}; + +class DDLFile +{ + HANDLE _hFile; + + bool ReadFile(void *data, size_t sz); +public: + DDLFile(void); + ~DDLFile(void); + + bool OpenDDLFile(WString filename); + bool EnumFiles(IDDLFileEnumerator &enmClass); + DDLData ExtractFile(unsigned long offset); + unsigned long GetFileSize(unsigned long offset); +}; diff --git a/DDLReader/DDLReader.cpp b/DDLReader/DDLReader.cpp new file mode 100644 index 0000000..2042ba3 --- /dev/null +++ b/DDLReader/DDLReader.cpp @@ -0,0 +1,67 @@ +// DDLReader.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DDLReaderDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp + +BEGIN_MESSAGE_MAP(CDDLReaderApp, CWinApp) + //{{AFX_MSG_MAP(CDDLReaderApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp construction + +CDDLReaderApp::CDDLReaderApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CDDLReaderApp object + +CDDLReaderApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp initialization + +BOOL CDDLReaderApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + + + CDDLReaderDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/DDLReader/DDLReader.h b/DDLReader/DDLReader.h new file mode 100644 index 0000000..08dbe48 --- /dev/null +++ b/DDLReader/DDLReader.h @@ -0,0 +1,49 @@ +// DDLReader.h : main header file for the DDLREADER application +// + +#if !defined(AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_) +#define AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp: +// See DDLReader.cpp for the implementation of this class +// + +class CDDLReaderApp : public CWinApp +{ +public: + CDDLReaderApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDDLReaderApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CDDLReaderApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_) diff --git a/DDLReader/DDLReader.rc b/DDLReader/DDLReader.rc new file mode 100644 index 0000000..f1fcb4b --- /dev/null +++ b/DDLReader/DDLReader.rc @@ -0,0 +1,278 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Czech resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) +#ifdef _WIN32 +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\DDLReader.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\DDLReader.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_EXPORTING DIALOGEX 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Exporting" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER | 0x1,7,39, + 172,14 + CTEXT "Exporting",IDC_STATIC,7,7,172,8 + CTEXT "Static",IDC_NAME,7,23,172,8 + PUSHBUTTON "Stop",IDC_BUTTON1,68,61,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_EXPORTING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ABOUTBOX "&About DDLReader..." + IDS_FILEOPENFAILED "Failed to open DDL" + IDC_HEADGROUP "Group" + IDC_HEADFNAME "Filename" + IDC_HEADSIZE "Size" + IDC_HEADOFFSET "Offset" + IDS_DDLFILTER "DDLFiles|*.ddl|All Files|*.*||" + IDC_GROUP_GRAPHICS "Graphics" + IDC_GROUP_SOUNDS "Sounds" + IDC_GROUP_FONTS "Fonts" + IDC_GROUP_BASIC "Basic graphics" +END + +STRINGTABLE +BEGIN + IDC_GROUP_ITEMS "Item graphics" + IDC_GROUP_MONSTERS "Monster graphics" + IDC_GROUP_DIALOGS "Dialog graphics" + IDC_GROUP_UNSPECIFIED "Unspecified" + IDC_GROUP_UNKNOWN "Unknown (%d)" + IDS_UNABLETOCREATEFILE "Unable to create target file: \r\n%1" + IDS_UNABLETOEXTACTDATA "Unable to extract data. General reading error" +END + +#endif // Czech resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About DDLReader" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "DDLReader Version 1.0",IDC_STATIC,40,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 2005",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP +END + +IDD_DDLREADER_DIALOG DIALOGEX 0, 0, 364, 262 +STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_APPWINDOW +CAPTION "DDLReader" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "List2",IDC_FILELIST,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,0,14,363,219 + LTEXT "Export to folder:",IDC_POPISEK,0,235,50,8 + EDITTEXT IDC_FOLDER,0,248,263,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_BROWSE,268,248,34,14 + PUSHBUTTON "Export",IDC_EXPORT,306,248,58,14 + EDITTEXT IDC_DDLFILE,0,0,313,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse DDL",IDC_DDLBROWSE,314,0,50,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "FileDescription", "DDLReader MFC Application" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "DDLReader" + VALUE "LegalCopyright", "Copyright (C) 2005" + VALUE "OriginalFilename", "DDLReader.EXE" + VALUE "ProductName", "DDLReader Application" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_DDLREADER_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 357 + TOPMARGIN, 7 + BOTTOMMARGIN, 255 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\DDLReader.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/DDLReader/DDLReader.sln b/DDLReader/DDLReader.sln new file mode 100644 index 0000000..cc4c08b --- /dev/null +++ b/DDLReader/DDLReader.sln @@ -0,0 +1,34 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DDLReader", "DDLReader.vcproj", "{A5326507-3420-4D03-B9EB-5583790B412B}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 2 + SccProjectName0 = \u0022$/Skeldal/DDLReader\u0022,\u0020NJEAAAAA + SccLocalPath0 = ..\\..\\.. + SccProvider0 = MSSCCI:Microsoft\u0020Visual\u0020SourceSafe + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection0 = Projects\\Skeldal\\DDLReader\\ + SolutionUniqueID = {A1A5598F-1F71-475C-8CAA-699B487DC20F} + SccProjectUniqueName1 = DDLReader.vcproj + SccLocalPath1 = ..\\..\\.. + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection1 = Projects\\Skeldal\\DDLReader\\ + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {A5326507-3420-4D03-B9EB-5583790B412B}.Debug.ActiveCfg = Debug|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Debug.Build.0 = Debug|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Release.ActiveCfg = Release|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/DDLReader/DDLReader.vcproj b/DDLReader/DDLReader.vcproj new file mode 100644 index 0000000..f50a9a4 --- /dev/null +++ b/DDLReader/DDLReader.vcproj @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DDLReader/DDLReaderDlg.cpp b/DDLReader/DDLReaderDlg.cpp new file mode 100644 index 0000000..a649500 --- /dev/null +++ b/DDLReader/DDLReaderDlg.cpp @@ -0,0 +1,533 @@ +// DDLReaderDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DDLReaderDlg.h" +#include ".\ddlreaderdlg.h" +#include "WPathname.h" +#include "DlgProgress.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg dialog + +CDDLReaderDlg::CDDLReaderDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDDLReaderDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDDLReaderDlg) + vFolder = _T(""); + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +CDDLReaderDlg::~CDDLReaderDlg() +{ + if (!_lastTemp.IsNull()) DeleteFile(_lastTemp); +} + +void CDDLReaderDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDDLReaderDlg) + DDX_Control(pDX, IDC_FOLDER, wFolder); + DDX_Control(pDX, IDC_FILELIST, wFileList); + DDX_Control(pDX, IDC_BROWSE, wBrowse); + DDX_Control(pDX, IDC_EXPORT, wExport); + DDX_Text(pDX, IDC_FOLDER, vFolder); + DDX_Control(pDX, IDC_POPISEK, wPopisek); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_DDLFILE, wDDLFile); + DDX_Control(pDX, IDC_DDLBROWSE, wDDLBrowse); +} + +BEGIN_MESSAGE_MAP(CDDLReaderDlg, CDialog) + //{{AFX_MSG_MAP(CDDLReaderDlg) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_EN_KILLFOCUS(IDC_DDLFILE, OnEnKillfocusDdlfile) + ON_BN_CLICKED(IDC_DDLBROWSE, OnBnClickedDdlbrowse) + ON_NOTIFY(LVN_COLUMNCLICK, IDC_FILELIST, OnLvnColumnclickFilelist) + ON_BN_CLICKED(IDC_BROWSE, OnBnClickedBrowse) + ON_BN_CLICKED(IDC_EXPORT, OnBnClickedExport) + ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg message handlers + +BOOL CDDLReaderDlg::OnInitDialog() +{ + CRect rc; + GetClientRect(&rc); + _dlgSize=rc.Size(); + CDialog::OnInitDialog(); + + // Add "About..." menu item to system menu. + + // IDM_ABOUTBOX must be in the system command range. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != NULL) + { + CString strAboutMenu; + strAboutMenu.LoadString(IDS_ABOUTBOX); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + CString header; + header.LoadString(IDC_HEADGROUP); + wFileList.InsertColumn(0,header,LVCFMT_CENTER,100,0); + header.LoadString(IDC_HEADFNAME); + wFileList.InsertColumn(1,header,LVCFMT_LEFT,140,1); + header.LoadString(IDC_HEADSIZE); + wFileList.InsertColumn(2,header,LVCFMT_RIGHT,80,2); + header.LoadString(IDC_HEADOFFSET); + wFileList.InsertColumn(3,header,LVCFMT_RIGHT,80,3); + ListView_SetExtendedListViewStyleEx(wFileList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP); + + // TODO: Add extra initialization here + + return TRUE; // return TRUE unless you set the focus to a control +} + +void CDDLReaderDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialog::OnSysCommand(nID, lParam); + } +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CDDLReaderDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CDDLReaderDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void MoveWindowRel(HDWP &hdwp, CWnd &wnd, int xr,int yr, int xs, int ys) +{ + CRect rc; + wnd.GetWindowRect(&rc); + wnd.GetParent()->ScreenToClient(&rc); + rc.left+=xr; + rc.top+=yr; + rc.bottom+=yr+ys; + rc.right+=xr+xs; + hdwp=DeferWindowPos(hdwp,wnd,NULL,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER); +} + +void CDDLReaderDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + if (nType!=SIZE_MINIMIZED) + { + if (wFileList.GetSafeHwnd()!=0) + { + HDWP dwp=BeginDeferWindowPos(10); + int difx=cx-_dlgSize.cx; + int dify=cy-_dlgSize.cy; + MoveWindowRel(dwp,wFileList,0,0,difx,dify); + MoveWindowRel(dwp,wPopisek,0,dify,0,0); + MoveWindowRel(dwp,wFolder,0,dify,difx,0); + MoveWindowRel(dwp,wExport,difx,dify,0,0); + MoveWindowRel(dwp,wBrowse,difx,dify,0,0); + MoveWindowRel(dwp,wDDLFile,0,0,difx,0); + MoveWindowRel(dwp,wDDLBrowse,difx,0,0,0); + EndDeferWindowPos(dwp); + + } + _dlgSize.cx=cx; + _dlgSize.cy=cy; + } +} + + +void CDDLReaderDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) +{ + CDialog::OnGetMinMaxInfo(lpMMI); + lpMMI->ptMinTrackSize.x=200; + lpMMI->ptMinTrackSize.y=150; + +} + +void CDDLReaderDlg::OnEnKillfocusDdlfile() +{ + CString name; + wDDLFile.GetWindowText(name); + if (_ddlfile.OpenDDLFile(WString(name.GetString()))==false) + AfxMessageBox(IDS_FILEOPENFAILED); + UpdateList(); +} + +static CString GetGroupName(int group) +{ + int id; + switch (group) + { + case 1: id= IDC_GROUP_GRAPHICS;break; + case 2: id= IDC_GROUP_SOUNDS;break; + case 3: id= IDC_GROUP_FONTS;break; + case 7: id= IDC_GROUP_BASIC;break; + case 8: id= IDC_GROUP_ITEMS;break; + case 9: id= IDC_GROUP_MONSTERS;break; + case 11: id= IDC_GROUP_DIALOGS;break; + case 0: id=IDC_GROUP_UNSPECIFIED;break; + default: id=IDC_GROUP_UNKNOWN;break; + } + CString res; + res.Format(id,group); + return res; +} + +bool CDDLReaderDlg::File(WString name, int group, unsigned long offset) +{ + LVITEM item; + CString grpname=GetGroupName(group); + wchar_t buff[40]; + item.iItem=wFileList.GetItemCount(); + item.iSubItem=0; + item.mask=LVIF_GROUPID|LVIF_TEXT; + item.iGroupId=group; + item.pszText=grpname.LockBuffer(); + int ipos=wFileList.InsertItem(&item); + wFileList.SetItemText(ipos,1,name); + wFileList.SetItemText(ipos,3,_ui64tow(offset,buff,10)); + grpname.UnlockBuffer(); + return true; +} + +void CDDLReaderDlg::UpdateList(void) +{ + CString tmp; + wFileList.DeleteAllItems(); + _ddlfile.EnumFiles(*this); + for (int i=0,cnt=wFileList.GetItemCount();iGetItemText(lParam1,sinfo.index); + sinfo.right=sinfo.list->GetItemText(lParam2,sinfo.index); + switch (sinfo.index) + { + case 0: + case 1: res=wcsicmp(sinfo.left,sinfo.right);break; + case 3: { + int l=_wtoi(sinfo.left); + int r=_wtoi(sinfo.right); + res=(l>r)-(lGetItemText(lParam1,3); + sinfo.right=sinfo.list->GetItemText(lParam2,3); + unsigned long l=_wtoi(sinfo.left); + unsigned long r=_wtoi(sinfo.right); + l=sinfo._ddlfile->GetFileSize(l); + r=sinfo._ddlfile->GetFileSize(r); + res=(l>r)-(llParam2)-(lParam1(pNMHDR); + for (int i=0,cnt=wFileList.GetItemCount();iiSubItem; + sinfo.list=&wFileList; + sinfo._ddlfile=&_ddlfile; + wFileList.SortItems(SortItemsInFileList,(LPARAM)&sinfo); + *pResult = 0; +} + +static int WINAPI PosBrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData) + { + const wchar_t *curpath=(const wchar_t *)lpData; + if (uMsg == BFFM_INITIALIZED) + { + if (curpath && curpath[0]) + { + ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)((LPCSTR)curpath)); + ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)((LPCSTR)curpath)); + } + } + else if (uMsg == BFFM_SELCHANGED) + { + wchar_t buff[_MAX_PATH]; + if (SHGetPathFromIDList((LPITEMIDLIST)lParam,buff)) + { + ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)buff); + } + } + return 0; + }; + +static bool PathBrowser(HWND hWnd, wchar_t *path /* MAX_PATH size */) +{ + BROWSEINFO brw; + memset(&brw,0,sizeof(brw)); + brw.hwndOwner=hWnd; + brw.pidlRoot=NULL; + brw.pszDisplayName=path; + brw.lParam=(LPARAM)path; + brw.ulFlags= BIF_RETURNONLYFSDIRS |BIF_STATUSTEXT|BIF_USENEWUI ; + brw.lpfn = (BFFCALLBACK)(PosBrowseCallbackProc); + LPITEMIDLIST il=SHBrowseForFolder( &brw ); + if (il==NULL) return false; + SHGetPathFromIDList(il,path); + IMalloc *shmalloc; + SHGetMalloc(&shmalloc); + shmalloc->Free(il); + if (path[0]==0) return false; + return true; +} + + +void CDDLReaderDlg::OnBnClickedBrowse() +{ + wchar_t path[MAX_PATH]; + wFolder.GetWindowText(path,MAX_PATH); + if (PathBrowser(*this,path)) + { + wFolder.SetWindowText(path); + } +} + +void CDDLReaderDlg::OnBnClickedExport() +{ + wchar_t path[MAX_PATH]; + wFolder.GetWindowText(path,MAX_PATH); + if (path[0]==0) OnBnClickedBrowse(); + wFolder.GetWindowText(path,MAX_PATH); + if (path[0]==0) return; + WPathname fpath; + fpath.SetDirectory(path); + POSITION pos=wFileList.GetFirstSelectedItemPosition(); + int max=wFileList.GetSelectedCount(); + int cur=0; + DlgProgress pb; + if (max) {pb.Create(IDD_EXPORTING);pb.CenterWindow(this);EnableWindow(FALSE);} + while (pos) + { + MSG msg; + pb.wProgress.SetRange(0,max); + pb.wProgress.SetPos(++cur); + int i=wFileList.GetNextSelectedItem(pos); + CString fname; + unsigned long offset; + fname=wFileList.GetItemText(i,1); + offset=(unsigned long)_wtoi64(wFileList.GetItemText(i,3)); + pb.wDesc.SetWindowText(fname); + if (PeekMessage(&msg,0,0,0,PM_NOREMOVE)==TRUE) AfxPumpMessage(); + if (pb.stop) break; + DDLData data=_ddlfile.ExtractFile(offset); + if (data.data!=NULL) + { + fpath.SetFilename(fname); + HANDLE hFile=CreateFile(fpath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + while (hFile==INVALID_HANDLE_VALUE) + { + CString msg; + AfxFormatString1(msg,IDS_UNABLETOCREATEFILE,fpath); + int retry=AfxMessageBox(msg,MB_ABORTRETRYIGNORE); + if (retry==IDABORT) {EnableWindow(TRUE);return;} + if (retry==IDIGNORE) break; + hFile=CreateFile(fpath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + } + if (hFile!=INVALID_HANDLE_VALUE) + { + DWORD written; + WriteFile(hFile,data.data,data.sz,&written,NULL); + CloseHandle(hFile); + } + } + else + { + CString msg; + AfxFormatString1(msg,IDS_UNABLETOEXTACTDATA,fpath); + AfxMessageBox(msg,MB_OK|MB_ICONSTOP); + } + } + EnableWindow(TRUE); + + +} + +WPathname CDDLReaderDlg::CreateTemp(int index) +{ + if (!_lastTemp.IsNull()) DeleteFile(_lastTemp); + CString fname; + unsigned long offset; + fname=wFileList.GetItemText(index,1); + offset=(unsigned long)_wtoi64(wFileList.GetItemText(index,3)); + _lastTemp.SetTempDirectory(); + _lastTemp.SetFileTitle(WSC("SkeldalDDLReader")); + _lastTemp.SetExtension(WSC(".")+WString(fname)); + DDLData data=_ddlfile.ExtractFile(offset); + if (data.data) + { + HANDLE hFile=CreateFile(_lastTemp,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + DWORD written; + WriteFile(hFile,data.data,data.sz,&written,NULL); + CloseHandle(hFile); + } + return _lastTemp; +} + +void CDDLReaderDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult) +{ + // TODO: Add your control notification handler code here + *pResult = 0; + int index=wFileList.GetNextItem(-1,LVNI_FOCUSED); + WPathname pth=CreateTemp(index); + ShellExecute(*this,0,pth,0,0,SW_NORMAL); +} diff --git a/DDLReader/DDLReaderDlg.h b/DDLReader/DDLReaderDlg.h new file mode 100644 index 0000000..e141af8 --- /dev/null +++ b/DDLReader/DDLReaderDlg.h @@ -0,0 +1,76 @@ +// DDLReaderDlg.h : header file +// + +#include "t:\h\atlmfc\include\afxwin.h" +#include "ddlfile.h" +#include "WPathname.h" +#if !defined(AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_) +#define AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg dialog + +class CDDLReaderDlg : public CDialog, public IDDLFileEnumerator +{ +// Construction + CSize _dlgSize; + WPathname _lastTemp; +public: + CDDLReaderDlg(CWnd* pParent = NULL); // standard constructor + ~CDDLReaderDlg(); + +// Dialog Data + //{{AFX_DATA(CDDLReaderDlg) + enum { IDD = IDD_DDLREADER_DIALOG }; + CEdit wFolder; + CListCtrl wFileList; + CButton wBrowse; + CButton wExport; + CString vFolder; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDDLReaderDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + //{{AFX_MSG(CDDLReaderDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnSize(UINT nType, int cx, int cy); + CStatic wPopisek; + CEdit wDDLFile; + CButton wDDLBrowse; + afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); + DDLFile _ddlfile; + afx_msg void OnEnKillfocusDdlfile(); + void UpdateList(void); + virtual bool File(WString name, int group, unsigned long offset); + afx_msg void OnBnClickedDdlbrowse(); + afx_msg void OnLvnColumnclickFilelist(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnBnClickedBrowse(); + afx_msg void OnBnClickedExport(); + afx_msg void OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult); + + WPathname CreateTemp(int index); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_) diff --git a/DDLReader/DlgProgress.cpp b/DDLReader/DlgProgress.cpp new file mode 100644 index 0000000..cccfd60 --- /dev/null +++ b/DDLReader/DlgProgress.cpp @@ -0,0 +1,41 @@ +// DlgProgress.cpp : implementation file +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DlgProgress.h" +#include ".\dlgprogress.h" + + +// DlgProgress dialog + +IMPLEMENT_DYNAMIC(DlgProgress, CDialog) +DlgProgress::DlgProgress(CWnd* pParent /*=NULL*/) + : CDialog(DlgProgress::IDD, pParent) +{ + stop=false; +} + +DlgProgress::~DlgProgress() +{ +} + +void DlgProgress::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_PROGRESS, wProgress); + DDX_Control(pDX, IDC_NAME, wDesc); +} + + +BEGIN_MESSAGE_MAP(DlgProgress, CDialog) + ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1) +END_MESSAGE_MAP() + + +// DlgProgress message handlers + +void DlgProgress::OnBnClickedButton1() +{ + stop=true; +} diff --git a/DDLReader/DlgProgress.h b/DDLReader/DlgProgress.h new file mode 100644 index 0000000..8e6e3fb --- /dev/null +++ b/DDLReader/DlgProgress.h @@ -0,0 +1,28 @@ +#pragma once +#include "t:\h\atlmfc\include\afxcmn.h" +#include "t:\h\atlmfc\include\afxwin.h" + + +// DlgProgress dialog + +class DlgProgress : public CDialog +{ + DECLARE_DYNAMIC(DlgProgress) + +public: + DlgProgress(CWnd* pParent = NULL); // standard constructor + virtual ~DlgProgress(); + +// Dialog Data + enum { IDD = IDD_EXPORTING }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + CProgressCtrl wProgress; + CStatic wDesc; + afx_msg void OnBnClickedButton1(); + bool stop; +}; diff --git a/DDLReader/IWStringEffect.h b/DDLReader/IWStringEffect.h new file mode 100644 index 0000000..f11bf5e --- /dev/null +++ b/DDLReader/IWStringEffect.h @@ -0,0 +1,36 @@ +#if !defined(AFX_IWSTRINGEFFECT_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) +#define AFX_IWSTRINGEFFECT_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include + +class IWStringEffect +{ +public: + ///function returns extra size that effect needs + /** + @param curSize size of string that enters to the effect + @return count of extra characters needs to effects; + */ + virtual unsigned long GetEffectExtraSize(unsigned long curSize) {return 0;} + + ///function renders begin of string. + /** Function returns number of characters rendered, and must be <= then size returned by GetEffectExtraSize() + @param renderPtr pointer to render buffer + @param curSize size of string that enters to the effect + @return number of characters rendered. Entered string will be rendered behind. + */ + virtual unsigned long PreRenderString(wchar_t *renderPtr,unsigned long curSize) {return 0;} + + ///function renders effect. + /** + @param renderPtr pointer to begin of render buffer. + @param rendered number of characters rendered by previous effect. Value doesn't point to the end + of buffer, function must add result of PreRenderString */ + virtual void RenderString(wchar_t *renderPtr, unsigned long rendered)=0; +}; + +#endif diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLFile.cpp b/DDLReader/Projects/Skeldal/DDLReader/DDLFile.cpp new file mode 100644 index 0000000..9f5b556 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLFile.cpp @@ -0,0 +1,93 @@ +#include "stdafx.h" +#include ".\ddlfile.h" + +DDLFile::DDLFile(void) +{ + _hFile=0; +} + +DDLFile::~DDLFile(void) +{ + if (_hFile!=0) CloseHandle(_hFile); +} + + + + +bool DDLFile::OpenDDLFile(WString filename) +{ + _hFile=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, + OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL); + if (_hFile==INVALID_HANDLE_VALUE) + { + _hFile=0; + return false; + } + return true; +} + +bool DDLFile::ReadFile(void *data, size_t sz) +{ + DWORD readed=0; + if (::ReadFile(_hFile,data,sz,&readed,NULL)==FALSE) return false; + if (readed!=sz) return false; + return true; +} + +bool DDLFile::EnumFiles(IDDLFileEnumerator &enmClass) +{ + unsigned long firstGroup; + unsigned long groupEndOffset; + unsigned long endGroups; + int i; + int ngroups; + SetFilePointer(_hFile,0,0,FILE_BEGIN); + if (ReadFile(&firstGroup,sizeof(firstGroup))==false) return false; + if (ReadFile(&groupEndOffset,sizeof(firstGroup))==false) return false; + unsigned long *group=(unsigned long *)alloca(groupEndOffset); + group[0]=firstGroup; + group[1]=groupEndOffset; + ngroups=groupEndOffset/8; + if (groupEndOffset!=8 && ReadFile(group+2,groupEndOffset-8)==false) return false; + SetFilePointer(_hFile,12,0,FILE_CURRENT); + if (ReadFile(&endGroups,sizeof(endGroups))==false) return false; + for (i=0;i(other); + dother.data=0;dother.sz=0; + } + DDLData& operator =(const DDLData &other) + { + DDLData &dother=const_cast(other); + data=other.data;sz=other.sz; + dother.data=0;dother.sz=0; + return *this; + } +}; + +class DDLFile +{ + HANDLE _hFile; + + bool ReadFile(void *data, size_t sz); +public: + DDLFile(void); + ~DDLFile(void); + + bool OpenDDLFile(WString filename); + bool EnumFiles(IDDLFileEnumerator &enmClass); + DDLData ExtractFile(unsigned long offset); + unsigned long GetFileSize(unsigned long offset); +}; diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReader.cpp b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.cpp new file mode 100644 index 0000000..2042ba3 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.cpp @@ -0,0 +1,67 @@ +// DDLReader.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DDLReaderDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp + +BEGIN_MESSAGE_MAP(CDDLReaderApp, CWinApp) + //{{AFX_MSG_MAP(CDDLReaderApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp construction + +CDDLReaderApp::CDDLReaderApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CDDLReaderApp object + +CDDLReaderApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp initialization + +BOOL CDDLReaderApp::InitInstance() +{ + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + + + CDDLReaderDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReader.h b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.h new file mode 100644 index 0000000..08dbe48 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.h @@ -0,0 +1,49 @@ +// DDLReader.h : main header file for the DDLREADER application +// + +#if !defined(AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_) +#define AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderApp: +// See DDLReader.cpp for the implementation of this class +// + +class CDDLReaderApp : public CWinApp +{ +public: + CDDLReaderApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDDLReaderApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CDDLReaderApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DDLREADER_H__9FE8F7F8_112D_4735_A4BA_5141A991D609__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReader.rc b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.rc new file mode 100644 index 0000000..f1fcb4b --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.rc @@ -0,0 +1,278 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Czech resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CSY) +#ifdef _WIN32 +LANGUAGE LANG_CZECH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\DDLReader.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "res\\DDLReader.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_EXPORTING DIALOGEX 0, 0, 186, 82 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Exporting" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER | 0x1,7,39, + 172,14 + CTEXT "Exporting",IDC_STATIC,7,7,172,8 + CTEXT "Static",IDC_NAME,7,23,172,8 + PUSHBUTTON "Stop",IDC_BUTTON1,68,61,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_EXPORTING, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 75 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ABOUTBOX "&About DDLReader..." + IDS_FILEOPENFAILED "Failed to open DDL" + IDC_HEADGROUP "Group" + IDC_HEADFNAME "Filename" + IDC_HEADSIZE "Size" + IDC_HEADOFFSET "Offset" + IDS_DDLFILTER "DDLFiles|*.ddl|All Files|*.*||" + IDC_GROUP_GRAPHICS "Graphics" + IDC_GROUP_SOUNDS "Sounds" + IDC_GROUP_FONTS "Fonts" + IDC_GROUP_BASIC "Basic graphics" +END + +STRINGTABLE +BEGIN + IDC_GROUP_ITEMS "Item graphics" + IDC_GROUP_MONSTERS "Monster graphics" + IDC_GROUP_DIALOGS "Dialog graphics" + IDC_GROUP_UNSPECIFIED "Unspecified" + IDC_GROUP_UNKNOWN "Unknown (%d)" + IDS_UNABLETOCREATEFILE "Unable to create target file: \r\n%1" + IDS_UNABLETOEXTACTDATA "Unable to extract data. General reading error" +END + +#endif // Czech resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG 0, 0, 235, 55 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About DDLReader" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "DDLReader Version 1.0",IDC_STATIC,40,10,119,8, + SS_NOPREFIX + LTEXT "Copyright (C) 2005",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP +END + +IDD_DDLREADER_DIALOG DIALOGEX 0, 0, 364, 262 +STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU | WS_THICKFRAME +EXSTYLE WS_EX_APPWINDOW +CAPTION "DDLReader" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "List2",IDC_FILELIST,"SysListView32",LVS_REPORT | + LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,0,14,363,219 + LTEXT "Export to folder:",IDC_POPISEK,0,235,50,8 + EDITTEXT IDC_FOLDER,0,248,263,14,ES_AUTOHSCROLL + PUSHBUTTON "Browse",IDC_BROWSE,268,248,34,14 + PUSHBUTTON "Export",IDC_EXPORT,306,248,58,14 + EDITTEXT IDC_DDLFILE,0,0,313,12,ES_AUTOHSCROLL + PUSHBUTTON "Browse DDL",IDC_DDLBROWSE,314,0,50,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "FileDescription", "DDLReader MFC Application" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "DDLReader" + VALUE "LegalCopyright", "Copyright (C) 2005" + VALUE "OriginalFilename", "DDLReader.EXE" + VALUE "ProductName", "DDLReader Application" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 228 + TOPMARGIN, 7 + BOTTOMMARGIN, 48 + END + + IDD_DDLREADER_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 357 + TOPMARGIN, 7 + BOTTOMMARGIN, 255 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\DDLReader.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReader.sln b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.sln new file mode 100644 index 0000000..cc4c08b --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.sln @@ -0,0 +1,34 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DDLReader", "DDLReader.vcproj", "{A5326507-3420-4D03-B9EB-5583790B412B}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 2 + SccProjectName0 = \u0022$/Skeldal/DDLReader\u0022,\u0020NJEAAAAA + SccLocalPath0 = ..\\..\\.. + SccProvider0 = MSSCCI:Microsoft\u0020Visual\u0020SourceSafe + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection0 = Projects\\Skeldal\\DDLReader\\ + SolutionUniqueID = {A1A5598F-1F71-475C-8CAA-699B487DC20F} + SccProjectUniqueName1 = DDLReader.vcproj + SccLocalPath1 = ..\\..\\.. + CanCheckoutShared = false + SccProjectFilePathRelativizedFromConnection1 = Projects\\Skeldal\\DDLReader\\ + EndGlobalSection + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {A5326507-3420-4D03-B9EB-5583790B412B}.Debug.ActiveCfg = Debug|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Debug.Build.0 = Debug|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Release.ActiveCfg = Release|Win32 + {A5326507-3420-4D03-B9EB-5583790B412B}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReader.vcproj b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.vcproj new file mode 100644 index 0000000..f50a9a4 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReader.vcproj @@ -0,0 +1,291 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.cpp b/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.cpp new file mode 100644 index 0000000..a649500 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.cpp @@ -0,0 +1,533 @@ +// DDLReaderDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DDLReaderDlg.h" +#include ".\ddlreaderdlg.h" +#include "WPathname.h" +#include "DlgProgress.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg dialog + +CDDLReaderDlg::CDDLReaderDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDDLReaderDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDDLReaderDlg) + vFolder = _T(""); + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +CDDLReaderDlg::~CDDLReaderDlg() +{ + if (!_lastTemp.IsNull()) DeleteFile(_lastTemp); +} + +void CDDLReaderDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDDLReaderDlg) + DDX_Control(pDX, IDC_FOLDER, wFolder); + DDX_Control(pDX, IDC_FILELIST, wFileList); + DDX_Control(pDX, IDC_BROWSE, wBrowse); + DDX_Control(pDX, IDC_EXPORT, wExport); + DDX_Text(pDX, IDC_FOLDER, vFolder); + DDX_Control(pDX, IDC_POPISEK, wPopisek); + //}}AFX_DATA_MAP + DDX_Control(pDX, IDC_DDLFILE, wDDLFile); + DDX_Control(pDX, IDC_DDLBROWSE, wDDLBrowse); +} + +BEGIN_MESSAGE_MAP(CDDLReaderDlg, CDialog) + //{{AFX_MSG_MAP(CDDLReaderDlg) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + //}}AFX_MSG_MAP + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_EN_KILLFOCUS(IDC_DDLFILE, OnEnKillfocusDdlfile) + ON_BN_CLICKED(IDC_DDLBROWSE, OnBnClickedDdlbrowse) + ON_NOTIFY(LVN_COLUMNCLICK, IDC_FILELIST, OnLvnColumnclickFilelist) + ON_BN_CLICKED(IDC_BROWSE, OnBnClickedBrowse) + ON_BN_CLICKED(IDC_EXPORT, OnBnClickedExport) + ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg message handlers + +BOOL CDDLReaderDlg::OnInitDialog() +{ + CRect rc; + GetClientRect(&rc); + _dlgSize=rc.Size(); + CDialog::OnInitDialog(); + + // Add "About..." menu item to system menu. + + // IDM_ABOUTBOX must be in the system command range. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != NULL) + { + CString strAboutMenu; + strAboutMenu.LoadString(IDS_ABOUTBOX); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + CString header; + header.LoadString(IDC_HEADGROUP); + wFileList.InsertColumn(0,header,LVCFMT_CENTER,100,0); + header.LoadString(IDC_HEADFNAME); + wFileList.InsertColumn(1,header,LVCFMT_LEFT,140,1); + header.LoadString(IDC_HEADSIZE); + wFileList.InsertColumn(2,header,LVCFMT_RIGHT,80,2); + header.LoadString(IDC_HEADOFFSET); + wFileList.InsertColumn(3,header,LVCFMT_RIGHT,80,3); + ListView_SetExtendedListViewStyleEx(wFileList,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP); + + // TODO: Add extra initialization here + + return TRUE; // return TRUE unless you set the focus to a control +} + +void CDDLReaderDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialog::OnSysCommand(nID, lParam); + } +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CDDLReaderDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CDDLReaderDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void MoveWindowRel(HDWP &hdwp, CWnd &wnd, int xr,int yr, int xs, int ys) +{ + CRect rc; + wnd.GetWindowRect(&rc); + wnd.GetParent()->ScreenToClient(&rc); + rc.left+=xr; + rc.top+=yr; + rc.bottom+=yr+ys; + rc.right+=xr+xs; + hdwp=DeferWindowPos(hdwp,wnd,NULL,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,SWP_NOZORDER); +} + +void CDDLReaderDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + if (nType!=SIZE_MINIMIZED) + { + if (wFileList.GetSafeHwnd()!=0) + { + HDWP dwp=BeginDeferWindowPos(10); + int difx=cx-_dlgSize.cx; + int dify=cy-_dlgSize.cy; + MoveWindowRel(dwp,wFileList,0,0,difx,dify); + MoveWindowRel(dwp,wPopisek,0,dify,0,0); + MoveWindowRel(dwp,wFolder,0,dify,difx,0); + MoveWindowRel(dwp,wExport,difx,dify,0,0); + MoveWindowRel(dwp,wBrowse,difx,dify,0,0); + MoveWindowRel(dwp,wDDLFile,0,0,difx,0); + MoveWindowRel(dwp,wDDLBrowse,difx,0,0,0); + EndDeferWindowPos(dwp); + + } + _dlgSize.cx=cx; + _dlgSize.cy=cy; + } +} + + +void CDDLReaderDlg::OnGetMinMaxInfo(MINMAXINFO* lpMMI) +{ + CDialog::OnGetMinMaxInfo(lpMMI); + lpMMI->ptMinTrackSize.x=200; + lpMMI->ptMinTrackSize.y=150; + +} + +void CDDLReaderDlg::OnEnKillfocusDdlfile() +{ + CString name; + wDDLFile.GetWindowText(name); + if (_ddlfile.OpenDDLFile(WString(name.GetString()))==false) + AfxMessageBox(IDS_FILEOPENFAILED); + UpdateList(); +} + +static CString GetGroupName(int group) +{ + int id; + switch (group) + { + case 1: id= IDC_GROUP_GRAPHICS;break; + case 2: id= IDC_GROUP_SOUNDS;break; + case 3: id= IDC_GROUP_FONTS;break; + case 7: id= IDC_GROUP_BASIC;break; + case 8: id= IDC_GROUP_ITEMS;break; + case 9: id= IDC_GROUP_MONSTERS;break; + case 11: id= IDC_GROUP_DIALOGS;break; + case 0: id=IDC_GROUP_UNSPECIFIED;break; + default: id=IDC_GROUP_UNKNOWN;break; + } + CString res; + res.Format(id,group); + return res; +} + +bool CDDLReaderDlg::File(WString name, int group, unsigned long offset) +{ + LVITEM item; + CString grpname=GetGroupName(group); + wchar_t buff[40]; + item.iItem=wFileList.GetItemCount(); + item.iSubItem=0; + item.mask=LVIF_GROUPID|LVIF_TEXT; + item.iGroupId=group; + item.pszText=grpname.LockBuffer(); + int ipos=wFileList.InsertItem(&item); + wFileList.SetItemText(ipos,1,name); + wFileList.SetItemText(ipos,3,_ui64tow(offset,buff,10)); + grpname.UnlockBuffer(); + return true; +} + +void CDDLReaderDlg::UpdateList(void) +{ + CString tmp; + wFileList.DeleteAllItems(); + _ddlfile.EnumFiles(*this); + for (int i=0,cnt=wFileList.GetItemCount();iGetItemText(lParam1,sinfo.index); + sinfo.right=sinfo.list->GetItemText(lParam2,sinfo.index); + switch (sinfo.index) + { + case 0: + case 1: res=wcsicmp(sinfo.left,sinfo.right);break; + case 3: { + int l=_wtoi(sinfo.left); + int r=_wtoi(sinfo.right); + res=(l>r)-(lGetItemText(lParam1,3); + sinfo.right=sinfo.list->GetItemText(lParam2,3); + unsigned long l=_wtoi(sinfo.left); + unsigned long r=_wtoi(sinfo.right); + l=sinfo._ddlfile->GetFileSize(l); + r=sinfo._ddlfile->GetFileSize(r); + res=(l>r)-(llParam2)-(lParam1(pNMHDR); + for (int i=0,cnt=wFileList.GetItemCount();iiSubItem; + sinfo.list=&wFileList; + sinfo._ddlfile=&_ddlfile; + wFileList.SortItems(SortItemsInFileList,(LPARAM)&sinfo); + *pResult = 0; +} + +static int WINAPI PosBrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lParam,LPARAM lpData) + { + const wchar_t *curpath=(const wchar_t *)lpData; + if (uMsg == BFFM_INITIALIZED) + { + if (curpath && curpath[0]) + { + ::SendMessage(hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)((LPCSTR)curpath)); + ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)((LPCSTR)curpath)); + } + } + else if (uMsg == BFFM_SELCHANGED) + { + wchar_t buff[_MAX_PATH]; + if (SHGetPathFromIDList((LPITEMIDLIST)lParam,buff)) + { + ::SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)buff); + } + } + return 0; + }; + +static bool PathBrowser(HWND hWnd, wchar_t *path /* MAX_PATH size */) +{ + BROWSEINFO brw; + memset(&brw,0,sizeof(brw)); + brw.hwndOwner=hWnd; + brw.pidlRoot=NULL; + brw.pszDisplayName=path; + brw.lParam=(LPARAM)path; + brw.ulFlags= BIF_RETURNONLYFSDIRS |BIF_STATUSTEXT|BIF_USENEWUI ; + brw.lpfn = (BFFCALLBACK)(PosBrowseCallbackProc); + LPITEMIDLIST il=SHBrowseForFolder( &brw ); + if (il==NULL) return false; + SHGetPathFromIDList(il,path); + IMalloc *shmalloc; + SHGetMalloc(&shmalloc); + shmalloc->Free(il); + if (path[0]==0) return false; + return true; +} + + +void CDDLReaderDlg::OnBnClickedBrowse() +{ + wchar_t path[MAX_PATH]; + wFolder.GetWindowText(path,MAX_PATH); + if (PathBrowser(*this,path)) + { + wFolder.SetWindowText(path); + } +} + +void CDDLReaderDlg::OnBnClickedExport() +{ + wchar_t path[MAX_PATH]; + wFolder.GetWindowText(path,MAX_PATH); + if (path[0]==0) OnBnClickedBrowse(); + wFolder.GetWindowText(path,MAX_PATH); + if (path[0]==0) return; + WPathname fpath; + fpath.SetDirectory(path); + POSITION pos=wFileList.GetFirstSelectedItemPosition(); + int max=wFileList.GetSelectedCount(); + int cur=0; + DlgProgress pb; + if (max) {pb.Create(IDD_EXPORTING);pb.CenterWindow(this);EnableWindow(FALSE);} + while (pos) + { + MSG msg; + pb.wProgress.SetRange(0,max); + pb.wProgress.SetPos(++cur); + int i=wFileList.GetNextSelectedItem(pos); + CString fname; + unsigned long offset; + fname=wFileList.GetItemText(i,1); + offset=(unsigned long)_wtoi64(wFileList.GetItemText(i,3)); + pb.wDesc.SetWindowText(fname); + if (PeekMessage(&msg,0,0,0,PM_NOREMOVE)==TRUE) AfxPumpMessage(); + if (pb.stop) break; + DDLData data=_ddlfile.ExtractFile(offset); + if (data.data!=NULL) + { + fpath.SetFilename(fname); + HANDLE hFile=CreateFile(fpath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + while (hFile==INVALID_HANDLE_VALUE) + { + CString msg; + AfxFormatString1(msg,IDS_UNABLETOCREATEFILE,fpath); + int retry=AfxMessageBox(msg,MB_ABORTRETRYIGNORE); + if (retry==IDABORT) {EnableWindow(TRUE);return;} + if (retry==IDIGNORE) break; + hFile=CreateFile(fpath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + } + if (hFile!=INVALID_HANDLE_VALUE) + { + DWORD written; + WriteFile(hFile,data.data,data.sz,&written,NULL); + CloseHandle(hFile); + } + } + else + { + CString msg; + AfxFormatString1(msg,IDS_UNABLETOEXTACTDATA,fpath); + AfxMessageBox(msg,MB_OK|MB_ICONSTOP); + } + } + EnableWindow(TRUE); + + +} + +WPathname CDDLReaderDlg::CreateTemp(int index) +{ + if (!_lastTemp.IsNull()) DeleteFile(_lastTemp); + CString fname; + unsigned long offset; + fname=wFileList.GetItemText(index,1); + offset=(unsigned long)_wtoi64(wFileList.GetItemText(index,3)); + _lastTemp.SetTempDirectory(); + _lastTemp.SetFileTitle(WSC("SkeldalDDLReader")); + _lastTemp.SetExtension(WSC(".")+WString(fname)); + DDLData data=_ddlfile.ExtractFile(offset); + if (data.data) + { + HANDLE hFile=CreateFile(_lastTemp,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); + DWORD written; + WriteFile(hFile,data.data,data.sz,&written,NULL); + CloseHandle(hFile); + } + return _lastTemp; +} + +void CDDLReaderDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult) +{ + // TODO: Add your control notification handler code here + *pResult = 0; + int index=wFileList.GetNextItem(-1,LVNI_FOCUSED); + WPathname pth=CreateTemp(index); + ShellExecute(*this,0,pth,0,0,SW_NORMAL); +} diff --git a/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.h b/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.h new file mode 100644 index 0000000..e141af8 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DDLReaderDlg.h @@ -0,0 +1,76 @@ +// DDLReaderDlg.h : header file +// + +#include "t:\h\atlmfc\include\afxwin.h" +#include "ddlfile.h" +#include "WPathname.h" +#if !defined(AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_) +#define AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CDDLReaderDlg dialog + +class CDDLReaderDlg : public CDialog, public IDDLFileEnumerator +{ +// Construction + CSize _dlgSize; + WPathname _lastTemp; +public: + CDDLReaderDlg(CWnd* pParent = NULL); // standard constructor + ~CDDLReaderDlg(); + +// Dialog Data + //{{AFX_DATA(CDDLReaderDlg) + enum { IDD = IDD_DDLREADER_DIALOG }; + CEdit wFolder; + CListCtrl wFileList; + CButton wBrowse; + CButton wExport; + CString vFolder; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDDLReaderDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + //{{AFX_MSG(CDDLReaderDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnSize(UINT nType, int cx, int cy); + CStatic wPopisek; + CEdit wDDLFile; + CButton wDDLBrowse; + afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); + DDLFile _ddlfile; + afx_msg void OnEnKillfocusDdlfile(); + void UpdateList(void); + virtual bool File(WString name, int group, unsigned long offset); + afx_msg void OnBnClickedDdlbrowse(); + afx_msg void OnLvnColumnclickFilelist(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnBnClickedBrowse(); + afx_msg void OnBnClickedExport(); + afx_msg void OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult); + + WPathname CreateTemp(int index); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DDLREADERDLG_H__E765355F_0112_4B3E_90CE_111E28FE8EC6__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.cpp b/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.cpp new file mode 100644 index 0000000..cccfd60 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.cpp @@ -0,0 +1,41 @@ +// DlgProgress.cpp : implementation file +// + +#include "stdafx.h" +#include "DDLReader.h" +#include "DlgProgress.h" +#include ".\dlgprogress.h" + + +// DlgProgress dialog + +IMPLEMENT_DYNAMIC(DlgProgress, CDialog) +DlgProgress::DlgProgress(CWnd* pParent /*=NULL*/) + : CDialog(DlgProgress::IDD, pParent) +{ + stop=false; +} + +DlgProgress::~DlgProgress() +{ +} + +void DlgProgress::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_PROGRESS, wProgress); + DDX_Control(pDX, IDC_NAME, wDesc); +} + + +BEGIN_MESSAGE_MAP(DlgProgress, CDialog) + ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1) +END_MESSAGE_MAP() + + +// DlgProgress message handlers + +void DlgProgress::OnBnClickedButton1() +{ + stop=true; +} diff --git a/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.h b/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.h new file mode 100644 index 0000000..8e6e3fb --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/DlgProgress.h @@ -0,0 +1,28 @@ +#pragma once +#include "t:\h\atlmfc\include\afxcmn.h" +#include "t:\h\atlmfc\include\afxwin.h" + + +// DlgProgress dialog + +class DlgProgress : public CDialog +{ + DECLARE_DYNAMIC(DlgProgress) + +public: + DlgProgress(CWnd* pParent = NULL); // standard constructor + virtual ~DlgProgress(); + +// Dialog Data + enum { IDD = IDD_EXPORTING }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() +public: + CProgressCtrl wProgress; + CStatic wDesc; + afx_msg void OnBnClickedButton1(); + bool stop; +}; diff --git a/DDLReader/Projects/Skeldal/DDLReader/IWStringEffect.h b/DDLReader/Projects/Skeldal/DDLReader/IWStringEffect.h new file mode 100644 index 0000000..f11bf5e --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/IWStringEffect.h @@ -0,0 +1,36 @@ +#if !defined(AFX_IWSTRINGEFFECT_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) +#define AFX_IWSTRINGEFFECT_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include + +class IWStringEffect +{ +public: + ///function returns extra size that effect needs + /** + @param curSize size of string that enters to the effect + @return count of extra characters needs to effects; + */ + virtual unsigned long GetEffectExtraSize(unsigned long curSize) {return 0;} + + ///function renders begin of string. + /** Function returns number of characters rendered, and must be <= then size returned by GetEffectExtraSize() + @param renderPtr pointer to render buffer + @param curSize size of string that enters to the effect + @return number of characters rendered. Entered string will be rendered behind. + */ + virtual unsigned long PreRenderString(wchar_t *renderPtr,unsigned long curSize) {return 0;} + + ///function renders effect. + /** + @param renderPtr pointer to begin of render buffer. + @param rendered number of characters rendered by previous effect. Value doesn't point to the end + of buffer, function must add result of PreRenderString */ + virtual void RenderString(wchar_t *renderPtr, unsigned long rendered)=0; +}; + +#endif diff --git a/DDLReader/Projects/Skeldal/DDLReader/StdAfx.cpp b/DDLReader/Projects/Skeldal/DDLReader/StdAfx.cpp new file mode 100644 index 0000000..1a90873 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// DDLReader.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/DDLReader/Projects/Skeldal/DDLReader/StdAfx.h b/DDLReader/Projects/Skeldal/DDLReader/StdAfx.h new file mode 100644 index 0000000..666c5f5 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/StdAfx.h @@ -0,0 +1,27 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_) +#define AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include "wstring.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/WPathname.cpp b/DDLReader/Projects/Skeldal/DDLReader/WPathname.cpp new file mode 100644 index 0000000..fab2f57 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WPathname.cpp @@ -0,0 +1,408 @@ +// WPathname.cpp: implementation of the WPathname class. +// +////////////////////////////////////////////////////////////////////// + +#include "WPathname.h" +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +WPathname::WPathname(const wchar_t *name /*=NULL*/) +{ + if (name) SetPathname(name); +} + +WPathname::WPathname(const WString &name) +{ + SetPathname(name); +} + +WPathname::WPathname(const wchar_t *relpath, const WPathname &abspath) +{ + _fullpath=WString(relpath); + int chr=_fullpath.FindLast('\\'); + if (chr!=-1) + { + _path=_fullpath.Left(chr+1); + _filetitle=_fullpath.Right(chr+1); + } + else + { + _filetitle=_fullpath; + } + chr=_filetitle.FindLast('.'); + if (chr!=-1) + { + _extension=_filetitle.Right(chr); + _filetitle=_filetitle.Left(chr); + } + + RelativeToFull(abspath); +} + + +WPathname::WPathname(const WPathname &other) +{ + _fullpath=other._fullpath; + _path=other._path; + _filetitle=other._filetitle; + _extension=other._extension; +} + +void WPathname::SetDrive(wchar_t dr) +{ + if (HasDrive()) + { + if (dr==0) _path=_path.Right(2); + else _path[0]=dr; + } + else if (dr!=0) + { + int np=IsNetworkPath(); + wchar_t buff[2]; + buff[0]=dr; + buff[1]=':'; + buff[2]=0; + if (np) + _path=WString(buff)+_path.Right(np); + else + _path=WString(buff)+_path; + + } + RebuildPath(); +} + +void WPathname::SetDirectory(const wchar_t *dir) +{ + bool copydrv; //directory doesn't contain drive, need copy from original + bool addslash; //directory doesn't ending by backslash, need add it + + int len=wcslen(dir); + copydrv=HasDrive(dir) || !HasDrive(); //copy original drive, if exists and directory doesn't contaion drive + if (wcsncmp(dir,L"\\\\",2)==0) copydrv=true; //network path, don't copy drive + addslash=len && dir[len-1]!='\\'; //add slash + if (copydrv) + _path=WString(dir); + else + _path=_path.Left(2)+WString(dir); + if (addslash) + _path+=WSC("\\"); + + RebuildPath(); +} + +void WPathname::SetFilename(const wchar_t *filename) +{ + WString wfilename=WString(filename); + int dot=wfilename.FindLast('.'); + if (dot==-1) + { + _filetitle=wfilename; + _extension=0; + } + else + { + _filetitle=wfilename.Left(dot); + _extension=wfilename.Right(dot); + } + + RebuildPath(); +} + +void WPathname::SetExtension(const wchar_t *ext) +{ + _extension=WString(ext); + RebuildPath(); +} + +void WPathname::SetFileTitle(const wchar_t *title) +{ + _filetitle=WString(title); + RebuildPath(); +} + +void WPathname::SetPathname(const wchar_t *pathname) +{ + SetPathname(WString(pathname)); +} + +void WPathname::SetPathname(const WString &pathname) +{ + if (pathname.GetLength()==0) SetNull(); + else + { + wchar_t *part; + DWORD needsz=GetFullPathNameW(pathname,0,NULL,&part); + wchar_t *fpth=(wchar_t *)alloca(needsz*sizeof(*fpth)); + GetFullPathNameW(pathname,needsz,fpth,&part); + part=wcsrchr(fpth,'\\'); + if (part) part++;else part=NULL; + if (part) + { + SetFilename(part); + *part=0; + } + else + SetFilename(WString()); + SetDirectory(fpth); + } +} + +const wchar_t *WPathname::GetNameFromPath(const wchar_t *path) +{ + const wchar_t *c=wcsrchr(path,'\\'); + if (c!=NULL) c++;else return path; + return c; +} + +const wchar_t *WPathname::GetExtensionFromPath(const wchar_t *path) +{ + const wchar_t *fname=GetNameFromPath(path); + const wchar_t *c=wcsrchr(fname,'.'); + if (c==NULL) c=wcsrchr(path,0); + return c; +} + +void WPathname::RebuildPath() +{ + _fullpath=_path+_filetitle+_extension; +} + +bool WPathname::GetDirectoryWithDriveWLBS(wchar_t *buff, size_t size) const +{ + size_t psize=wcslen(GetDirectoryWithDrive()); + if (psize>size) return false; + if (psize==0) {buff[0]=0;return true;} + wcsncpy(buff,GetDirectoryWithDrive(),psize-1); + buff[psize-1]=0; + return true; +} + +WString WPathname::GetDirectoryWithDriveWLBS() const +{ + if (_path.GetLength()) return _path.Left(_path.GetLength()-1); + return WString(); +} + +bool WPathname::IsPathValid() const +{ + if (IsNull()) return false; + wchar_t *invalidChars=L"/*?\"<>|"; + const wchar_t *path=GetFullPath(); + if (*path==0) return false; + while (*path) + { + if (wcschr(invalidChars,*path)!=NULL) return false; + path++; + } + return true; +} + +bool WPathname::SetTempDirectory() +{ + wchar_t buff[1]; + DWORD size=GetTempPathW(1,buff); + if (size==0) return false; + WString pth; + wchar_t *p=pth.CreateBuffer(size); + if (GetTempPathW(size,p)==0) return false; + pth.UnlockBuffer(); + _path=pth; + return true; +} + +bool WPathname::SetDirectorySpecial(int nSpecCode) +{ + wchar_t buff[MAX_PATH]; + if (SHGetSpecialFolderPathW(GetForegroundWindow(),buff,nSpecCode,FALSE)!=NOERROR) return false; + SetDirectory(buff); + return true; +} + +bool WPathname::SetTempFile(const wchar_t *prefix, unsigned int unique) +{ + wchar_t tempname[MAX_PATH]; + if (GetTempFileNameW(GetDirectoryWithDrive(),prefix,unique,tempname)==0) return false; + this->SetPathname(tempname); + return true; +} + +WPathname WPathname::GetExePath() +{ + wchar_t buff[MAX_PATH*4]; + GetModuleFileNameW(NULL,buff,sizeof(buff)); + return WPathname(buff); +} + +const wchar_t *WPathname::FullToRelativeProjectRoot(const wchar_t *full, const wchar_t *projectRoot) +{ + const wchar_t *a=full,*b=projectRoot; + while (*a && towlower(*a)==towlower(*b)) {a++;b++;}; + if (*b) return full; + return a; +} + +bool WPathname::FullToRelative(const WPathname &relativeto) +{ + if (relativeto.IsNull() || IsNull()) return false; + bool h1=HasDrive(); + bool h2=relativeto.HasDrive(); + if (h1!=h2) return false; //rozdilny zpusob adresace - nelze vytvorit relatvni cestu + if (h1==true && h2==true && towupper(GetDrive())!=towupper(relativeto.GetDrive())) + return false; //ruzne disky, nelze vytvorit relativni cestu + if (wcsncmp(_path,L"\\\\",2)==0) //sitova cesta + { + int slsh=0; //citac lomitek + const wchar_t *a=_path; + const wchar_t *b=relativeto._path; + while (towupper(*a)==towupper(*b) && *a && slsh<3) //zacatek sitove cesty musi byt stejny + { + if (*a=='\\') slsh++; + a++;b++; + } + if (slsh!=3) return false; //pokud neni stejny, nelze vytvorit relativni cestu + } + int sublevel=0; + const wchar_t *ps1=_path; + const wchar_t *ps2=relativeto._path; + if (h1) {ps1+=2;ps2+=2;} + const wchar_t *sls=ps2; + while (towupper(*ps1)==towupper(*ps2) && *ps1) + { + if (*ps2=='\\') sls=ps2+1; + ps1++;ps2++; + } + ps1-=ps2-sls; + if (sls) + { + while (sls=wcschr(sls,'\\')) + { + sls++; + sublevel++; + } + } + wchar_t *buff=(wchar_t *)alloca((sublevel*3+wcslen(ps1)+1)*sizeof(*buff)); + wchar_t *pos=buff; + for (int i=0;iref._path.GetString()) + { + end--; + while (end>ref._path.GetString() && end[-1]!='\\') end--; + } + beg+=3; + } + else + beg+=2; + } + int partln=end-ref._path; + wchar_t *buff=(wchar_t *)alloca((partln+wcslen(beg)+1)*sizeof(*buff)); + wcsncpy(buff,ref._path,partln); + wcscpy(buff+partln,beg); + SetDrive(0); + SetDirectory(buff); + return true; +} + +int WPathname::IsNetworkPath() const +{ + if (wcsncmp(_path,L"\\\\",2)==0) //sitova cesta + { + const wchar_t *p=_path+2; + const wchar_t *c=wcschr(p,'\\'); + if (c) return c-_path; + } + return 0; +} + +void WPathname::SetServerName(const wchar_t *server) +{ + if (HasDrive()) SetDrive(0); + else + { + int np=IsNetworkPath(); + _path=_path.Right(np); + } + + _path=WSC("\\\\")+WString(server)+WSC("\\"); + RebuildPath(); +} + +void WPathname::SetNull() +{ + _fullpath=_path=_filetitle=_extension=0; +} + +bool WPathname::GetPartFromPath(const wchar_t *path, int partnum, wchar_t *buff, int bufsize, int mode) +{ + const wchar_t *scan=path; + while (*scan=='\\') scan++; + while (partnum && *scan) + { + while (*scan!='\\' && *scan) scan++; + while (*scan=='\\') scan++; + partnum--; + } + if (*scan==0) + { + buff[0]=0; + return false; + } + int pt=0; + if (mode==-1) + { + pt=scan-path; + if (pt>bufsize) + { + buff[0]=0; + return true; + } + else + memcpy(buff,path,pt); + } + bool nlast=false; + while (*scan && (mode==1 || !nlast) && pt 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WString.h" + +#ifndef ASSERT +#ifdef _DEBUG +#define ASSERT(x) assert(x) +#else +#define ASSERT(x) +#endif +#endif + +#define WPathnameCompare(op) bool operator op (const WPathname &other) const \ +{if (IsNull() || other.IsNull()) return false;else return wcsicmp(_fullpath,other._fullpath) op 0;}\ + bool operator op (const wchar_t *other) const \ +{ASSERT(!other || other[0]!=0);\ + if (IsNull() || other==NULL) return false;else return wcsicmp(_fullpath,other) op 0;} + +/** class WPathname simplifying manipulation with WPathnames, filenames, general paths, and +also supports convert from absolute path to relative respectively */ + + + +class WPathname +{ + ///object value and data + /**The implementation of WPathname creates only one buffer for all variables. It can + increase speed by effective memory use. Strings are stored one after another separated + by zero byte. Evry time any string changed, implementation recalculate buffer usage, and + decide, whether it should resize buffer or not. + + _fullpath also points to string contain full path with filename, + it is dominant value of the class + */ + WString _fullpath; + WString _path; /// + If name is provided, WPathname will expand it into full name with drive and folder name. + @param name optional argument to inicialize object + */ + WPathname(const wchar_t *name=NULL); + WPathname(const WString &name); + + ///Construct WPathname class + /** + @param relpath Relative path or uncomplette path or single filename with extension. + WPathname will expand this WPathname into full using absolute path provided by the second + argument. + @param abspath Absolute path used as reference to folder - the origin of relative path + provided in the first argument. + */ + WPathname(const wchar_t *relpath, const WPathname &abspath); + + ///Construct WPathname as copy of another WPathname + WPathname(const WPathname &other); + + + ///Function returns the current drive letter. + /** Before usage, ensure, that current WPathname contain drive. + In network path drive letter is missing. + In this case, result is undefined. To ensure, use HasDrive function + @return the drive letter of current path. + */ + wchar_t GetDrive() const + { + if (IsNull()) return 0; + return _path[0]; + } + + ///Static function determines, if argument contain a drive information. + /** + @param dir directory to inspect + @return true, if directory contain drive.

+ This function is independed, it don't need any WPathname variable declared. + */ + static bool HasDrive(const wchar_t *dir) + {return (dir[0]>='A' && dir[0]<='Z' || dir[0]>='a' && dir[0]<='z') && dir[1]==':';} + + ///Function determines, if current WPathname contain a drive information + /** + @return true, if current WPathname contain a drive information + */ + bool HasDrive() const + { + if (IsNull()) return false; + return HasDrive(_path); + } + + + ///Function returns current folder name + /** + if current folder name contain drive, only folder name is returned (without drive). + In other cases (relative or network drives) returns full path. + @return folder name or full path. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetDirectory() const + { + if (HasDrive()) return _path.GetString()+3; + else return _path.GetString()+IsNetworkPath(); + } + + const wchar_t *GetDirectoryWithDrive() const + { + return _path; + } + + ///Function returns current filename with extension + /** + @return current filename with extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetFilename() const + { + if (IsNull()) return NULL; + const wchar_t *blk=wcsrchr(_fullpath,'\\'); + if (blk) blk=blk+1;else blk=_fullpath; + return blk; + } + + ///Function returns current extension (with starting dot) + /** + @return current extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetExtension() const + {return _extension;} + + ///Function returns current filename without extension (without dot) + /** + @return current filename without extension (without dot). Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetTitle() const + {return _filetitle;} + + ///Function changes current drive. + /**If object contain WPathname with drive, then current drive is changed and function returns. + If object contain network path, then computer name is changed to the drive name. + If object contain relative path, then whole path is replaced by path on root on drive. + @param dr new drive letter. This parameter can be set to zero. It means, that current + driver is deleted, and path is converted to relative path from root. Note: Zero c + cannot be used with network paths and relative paths, and finnaly has no effect to the object + */ + + void SetDrive(wchar_t dr); + + ///Sets new directory for object + /** if object contain a drive letter and argument dir doesn't, then current drive is remain + and only directory part is replaced. If current path is network path or relative path, + then whole path is replaced by new one. + If argument dir contain drive letter, then whole path is replaced too. + @param dir contain new WPathname. Backslash should be the last wchar_tacter in string + */ + void SetDirectory(const wchar_t *dir); + + ///Sets new filename for object. + /** + If filename contain dot, function assumes, that filename is provided with extension. + Otherwise, current extension remains untouched. + @param filename new filename for object + */ + + void SetFilename(const wchar_t *filename); + + ///Sets new extension for object. + /** + If ext doesn't starting with dot, function adds it. + @param ext new extension for object + */ + void SetExtension(const wchar_t *ext); + + ///Sets new file title + /** Function changes file title, extension remains untouched. + if title contains extension (dot inside its name), this extension doesn't change + current extension. For example, if current extension is ".cpp" and filetitle contain + "source.h", then result is "source.h.cpp" + @param title a new title for object. + */ + + void SetFileTitle(const wchar_t *title); + + ///Function returns full WPathname. + /** + @return current WPathname. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + + const wchar_t *GetFullPath() const + {return _fullpath;} + + ///Sets WPathname + /** Function has same effect as constructor. But it can be used + anytime during object lifetime. It simply replaces current WPathname with newer. WPathname + in argument is expanded to full WPathname, current directory is used as reference. + @param WPathname new WPathname + */ + void SetPathname(const wchar_t *pathname); + void SetPathname(const WString &pathname); + + WPathname& operator=(const wchar_t *other) + {SetPathname(other);return *this;} + + WPathname& operator=(const WString &other) + {SetPathname(other);return *this;} + + WPathname& operator=(const WPathname& other) + { + _fullpath=other._fullpath; + _path=other._path; + _filetitle=other._filetitle; + _extension=other._extension; + return *this; + } + + ///converts object to string + operator const wchar_t *() const + {return GetFullPath();} + + ///Static function to help getting filename from WPathname + /** Function finds last backslash / and return pointer to first wchar_tacter after it. + Pointer stays valid until original path is destroyed or until original path is changed + @param path WPathname to inspect as string + @return pointer to filename + */ + static const wchar_t *GetNameFromPath(const wchar_t *path); + + ///Static function to help getting extension from WPathname + /** Function finds last dot '.' in filename return pointer to it (extension with dot). + Pointer stays valid until original path is destroyed or until original path is changed + @param path WPathname to inspect as string + @return pointer to extension + */ + static const wchar_t *GetExtensionFromPath(const wchar_t *path); + + ///Function sets server name for network path + /** If current path is network path, then changes server name to newer. Otherwise + it remove drive letter, and insert server name before remain path + @param server server name without slashes + */ + void SetServerName(const wchar_t *server); + + ///Function inspects current path and returns, whether contain server name + /**@return zero, if current path is not valid network path. Nonzero if path contain + server name. Then value returned count wchar_tacters containing server name with precedent + slashes. + */ + int IsNetworkPath() const; + + ///Function converts current relative path into absolute path + /** + If current path is not relative, function do nothing. + @param ref reference to path, against which path is relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool RelativeToFull(const WPathname &ref); + + ///Function converts current absolute path into relative path + /** + If current path is not relative, function do nothing. Both paths must be on the same + drive or network computer. + + @param ref reference to path, against which path should be relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool FullToRelative(const WPathname &relativeto); + + WPathname& operator+=(const wchar_t *relativePath) + {*this=WPathname(relativePath,*this);return *this;} + + WPathname operator+(const wchar_t *relativePath) + {WPathname out(relativePath,*this);return out;} + + bool IsNull() const {return _fullpath.GetLength()==0;} + + void SetNull(); + + WPathnameCompare(<) + WPathnameCompare(>) + WPathnameCompare(==) + WPathnameCompare(>=) + WPathnameCompare(<=) + WPathnameCompare(!=) + + + ///Function gets part of WPathname + /** + @param path subject of examine + @param partnum zero-base index of part of WPathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count wchar_tacters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + static bool GetPartFromPath(const wchar_t *path, int partnum, wchar_t *buff, int bufsize, int mode=0); + + ///Function gets part of object + /** + @param partnum zero-base index of part of WPathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count wchar_tacters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + bool GetPart(int partnum, wchar_t *buff, int bufsize,int mode=0) const + { + return GetPartFromPath(this->_fullpath,partnum,buff,bufsize,mode); + } + + /// Get Directory With Drive Without Last Back Slash + /** Retrieves into buffer directory with drive and removes last backslash + @param buff buffer that retrieves path + @param size size of buffer + @return true, if success, failed if buffer is too small*/ + + + bool GetDirectoryWithDriveWLBS(wchar_t *buff, size_t size) const; + + WString GetDirectoryWithDriveWLBS() const; + + + /// function checks, if path is valid and returns true, if does. + bool IsPathValid() const; + + /// Sets special directory. + /** + @param bSpecCode this value may be operation-system + depend. Windows implementation using CSIDL_XXXX constants, which is described in SHGetSpecialFolderLocation function + description + @return true, if function were successful + */ + bool SetDirectorySpecial(int nSpecCode); + + ///Sets temporaly directory. + bool SetTempDirectory(); + + ///Guess temporaly file name + /** + @param prefix prefix string for name + @param unique if unique is non-zero, it is used for new temporaly file. If unique is zero, function guess own unique + value. + @return true if function were successful + */ + bool SetTempFile(const wchar_t *prefix=L"tmp", unsigned int unique=NULL); + + ///Returns path of current executable. + /**It useful, when accessing folder, from when current module has been executed */ + static WPathname GetExePath(); + + ///Solves most used conversion from fullpath to path relative to project root + /** + @param full full WPathname with drive + @param projectRoot project root path + @return function returns pointer to full path, where starts relative part. If + fullpath doesn't contain project root path, it returns pointer to full. + @example FullToProjectRoot("x:\\project\\data\\example.txt","x:\\project"); //result is "data\\example.txt" + */ + + static const wchar_t *FullToRelativeProjectRoot(const wchar_t *full, const wchar_t *projectRoot); + + +protected: + ///Function only rebuild _fullpath string. + /** It doesn't check space for string! This function is used, when length of path is excepted + the same or smaller, then current. + */ + void RebuildPath(); + + +}; + + + +#endif // !defined(AFX_WPathname_H__158F59D5_B422_4FA6_86AC_10B5EC48C81B__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/WString.cpp b/DDLReader/Projects/Skeldal/DDLReader/WString.cpp new file mode 100644 index 0000000..a7e61e7 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WString.cpp @@ -0,0 +1,193 @@ +// WString.cpp: implementation of the WString class. +// +////////////////////////////////////////////////////////////////////// + +#include "WString.h" +#include +#include + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +WString::WString(const char *sbstring, unsigned int codePage) +{ + if (sbstring==NULL || *sbstring==0) + { + _ref=NULL; + } + else + { + size_t reqBuff=MultiByteToWideChar(codePage,0,sbstring,-1,NULL,0); + + _ref=WStringMemory::AllocString(NULL,reqBuff); + _ref->AddRef(); + wchar_t *str=const_cast(_ref->GetStringFromMemBlock()); + + MultiByteToWideChar(codePage,0,sbstring,-1,str,reqBuff); + } +} + +int WString::FormatV(wchar_t *format, va_list lst) +{ + size_t curSize=4096; + int written; + do + { + _ref=WStringMemory::AllocString(NULL,curSize); + wchar_t *str=const_cast(_ref->GetStringFromMemBlock()); + written=_vsnwprintf(str,curSize,format,lst); + if (written<0) + { + curSize*=2; + WStringMemory::FreeProxy(_ref); + } + } + while (written<-1); + _ref->RecalcLength(); + _ref->AddRef(); + return written; +} + +int WString::Format(wchar_t *format, ...) +{ + va_list valst; + va_start(valst,format); + return FormatV(format,valst); +} + + +int WString::ScanStringV(const wchar_t *format, va_list lst) const +{ + unsigned long *ptr=(unsigned long *)lst; + return swscanf(GetString(),format,ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],ptr[6],ptr[7],ptr[8],ptr[9], + ptr[10],ptr[11],ptr[12],ptr[13],ptr[14],ptr[15],ptr[16],ptr[17],ptr[18],ptr[19]); + +} + +int WString::ScanString(const wchar_t *format, ...) const +{ + va_list valst; + va_start(valst,format); + return ScanStringV(format,valst); +} + +bool WString::ReplaceOnce(const WString &findWhat,const WString &replaceWith) +{ + int pos=Find(findWhat); + if (pos==-1) return false; + (*this)=Left(pos)+replaceWith+Right(pos+replaceWith.GetLength()); + return true; +} + +bool WString::ReplaceAll(const WString &findWhat,const WString &replaceWith) +{ + WString process=*this; + WString result; + int pos; + bool processed=false; + while ((pos=process.Find(findWhat))!=-1) + { + result=result+process.Left(pos)+replaceWith; + process=process.Right(pos+findWhat.GetLength()); + processed=true; + } + *this=result+process; + return processed; +} + +WString WString::TrimLeft() const +{ + return TrimLeft(L" \r\n\t"); +} + +WString WString::TrimRight() const +{ + return TrimRight(L" \r\n\t"); +} + +WString WString::TrimLeft(wchar_t *trimChars) const +{ + const wchar_t *proStr=GetString(); + int p=0; + while (proStr[p] && wcschr(trimChars,proStr[p]!=NULL)) p++; + return Right(p); +} + +WString WString::TrimRight(wchar_t *trimChars) const +{ + const wchar_t *proStr=GetString(); + int p=GetLength()-1; + while (p>=0 && wcschr(trimChars,proStr[p]!=NULL)) p--; + return Left(p+1); +} + +WString WString::Upper() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfUpper))); +} + +WString WString::Lower() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfLower))); +} + +WString WString::Reverse() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfReverse))); +} + +WString WString::Effect(IWStringEffect *effect) const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,effect))); +} + +void WString::SetUTF7(const char *utf7) +{ + *this=WString(utf7,CP_UTF7); +} + +void WString::SetUTF8(const char *utf8) +{ + *this=WString(utf8,CP_UTF8); +} + +const char *WString::AsSBString(unsigned int codePage, WString &holder) +{ + const wchar_t *str=GetString(); + size_t reqsize=WideCharToMultiByte(codePage,0,str,-1,NULL,0,NULL,NULL); + WStringProxy *holderProxy=WStringMemory::AllocString(NULL,reqsize/2); //reqsize/2+(2 bytes) + char *mbstr=reinterpret_cast(const_cast(holderProxy->GetStringFromMemBlock())); + WideCharToMultiByte(codePage,0,str,-1,mbstr,reqsize,NULL,NULL); + holder=WString(holderProxy); + return mbstr; +} + +const char *WString::AsUTF7(WString &holder) +{ + return AsSBString(CP_UTF7,holder); +} + +const char *WString::AsUTF8(WString &holder) +{ + return AsSBString(CP_UTF8,holder); +} + +void WString::ReadFromStream(size_t (*streamReader)(wchar_t *buffer, size_t bufferLen, void *context),void *context) +{ + _ref->Release(); + _ref=NULL; + wchar_t buff[256]; + size_t rd; + while ((rd=streamReader(buff,sizeof(buff)/sizeof(wchar_t),context))!=0) + { + *this=*this+WString(buff,rd); + } +} + +const WString WStringConst(const wchar_t *text) +{ + return WString(WStringMemory::AllocProxy(WStringProxy(text))); +} + diff --git a/DDLReader/Projects/Skeldal/DDLReader/WString.h b/DDLReader/Projects/Skeldal/DDLReader/WString.h new file mode 100644 index 0000000..a244adb --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WString.h @@ -0,0 +1,496 @@ +// WString.h: interface for the WString class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_) +#define AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WStringProxy.h" +#include + +class WString +{ + mutable WStringProxy *_ref; + + + +public: + ///constructs empty string + WString():_ref(0) {} + + ///constructs string. + explicit WString(const wchar_t *string):_ref(string==NULL?NULL:WStringMemory::AllocString(string,0)) {_ref->AddRef();}; + + ///constructs string from wide-char array with specified length + WString(const wchar_t *string, size_t sz):_ref(WStringMemory::AllocString(string,sz)) {_ref->AddRef();}; + + ///copy constructor + /**constructor doesn't copy the string, only reference. + String is shared until it is changed + */ + WString(const WString &other):_ref(other._ref) {_ref->AddRef();} + + ///constructs string from multi-byte string. codePage specified code page of string + WString(const char *sbstring, unsigned int codePage); + + ///constructs string from string-proxy. Used internally with WStringMemory::AllocXXX functions + WString(WStringProxy *proxy):_ref(proxy) {_ref->AddRef();} + + ///assignment operator + /** assignment operator doesn't copy the string only reference. + String is shared until it is changed */ + WString &operator=(const WString &other) + {other._ref->AddRef();_ref->Release();_ref=other._ref;return *this;} + + ///Destructor - releases reference + ~WString() {_ref->Release();} + + ///function converts instance of WString to wchar_t pointer + /** + Function will perform RenderString, if it is needed. + */ + const wchar_t *GetString() const + { + if (_ref==NULL) return L""; + WStringProxy *str=_ref->RenderString(); + if (_ref!=str) + { + str->AddRef();_ref->Release();_ref=str; + } + return _ref->GetStringFromMemBlock(); + } + + ///operator can convert WString to wchar_t pointer anytime + operator const wchar_t *() const {return GetString();} + + ///function returns count of characters in string + /** function doesn't need to render string, so it can be called anytime + without loosing the benefit of "pseudo-strings" boosting */ + size_t GetLength() const + { + if (_ref) return _ref->GetLength(); + else return 0; + } + + ///function creates string as sum of this and another string + /** function creates "pseudo-string" that represents sum of two string. + pseudo-string is rendered to "real-string" automatically, when it is needed */ + WString operator+(const WString other) const + { + if (_ref==NULL) return other; + if (other._ref==NULL) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,other._ref))); + } + + WString &operator+=(const WString other) + { + *this=*this+other; + return *this; + } + + ///function creates string as substring of another string + /** function creates "pseudo-string" that represents substring of anothers string. + Pseudo-string is rendered to "real-string" automatically, when it is needed */ + WString Mid(size_t begin, size_t len) const + { + if (begin==0) return Left(len); + if (_ref==NULL || begin>GetLength()) return WString(); + if (begin+len>GetLength()) return Right(begin); + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,begin,len))); + } + + WString Left(size_t len) const + { + if (_ref==NULL) return WString(); + if (len>=GetLength()) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,0,len))); + } + + WString Right(size_t begin) const + { + if (_ref==NULL || begin>GetLength()) return WString(); + if (begin==0) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,begin,GetLength()-begin))); + } + + WString RightR(size_t count) const + { + if (_ref==NULL || count==0) return WString(); + if (count>=GetLength()) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,GetLength()-count,count))); + } + + WString Delete(size_t begin, size_t count) const + { + if (_ref==NULL) return WString(); + if (begin==0) return Right(count); + if (begin+count>=GetLength()) return Left(begin); + return WString(WStringMemory::AllocProxy(WStringProxy(Left(begin)._ref,Right(begin+count)._ref))); + } + + WString Insert(const WString &what, size_t index) const + { + if (_ref==NULL) return what; + if (index==0) return what+*this; + if (index>=GetLength()) return *this+what; + return Left(index)+what+Right(index); + } + + /// function allows to access any char in string + wchar_t operator[](int index) const + { + assert(index<=(int)GetLength() && index>=0); + return GetString()[index]; + } + + /// functions allows lock string for accesing it directly. + /** Function returns pointer to buffer which holds string. + Buffer size is equal to string length plus terminating zero. + Application can modify content of buffer. + If string is shared with another WString object, LockBuffer + creates copy of string + Do not forger to call UnlockBuffer, when you finish modifiing the content + */ + wchar_t *LockBuffer() + { + if (_ref==NULL) return NULL; + GetString(); + WStringMemory::LockProxy(_ref); + if (_ref->IsShared()) + { + WStringMemory::UnlockProxy(_ref); + _ref->Release(); + _ref=WStringMemory::AllocString(_ref->GetStringFromMemBlock(),0); + _ref->AddRef(); + WStringMemory::LockProxy(_ref); + } + return const_cast(_ref->GetStringFromMemBlock()); + } + + /// Function creates buffer for string and returns its address + /** Application can use buffer in functions, that cannot work with + WString objects. Size of buffer is specified by sz value, and it is in characters. + Application must call UnlockBuffer after writes all data into buffer. + + NOTE: Prevoius content of string is lost. + NOTE: sz specifies buffer size without terminating zero character + */ + wchar_t *CreateBuffer(size_t sz) + { + _ref->Release(); + _ref=WStringMemory::AllocString(NULL,sz); + _ref->AddRef(); + WStringMemory::LockProxy(_ref); + return const_cast(_ref->GetStringFromMemBlock()); + } + + /// Function creates buffer, and copies string into it. + /** Parameter sz specifies size of new buffer in characters + When sz is smaller then size of string, string is truncated + When sz is larger then size of string, string is copied unchanged, + but extra characters can be appended. + + NOTE: sz specifies buffer size without terminating zero character + */ + wchar_t *CreateBufferCopy(size_t sz) + { + WString save=*this; + wchar_t *wbuff=CreateBuffer(sz); + int minsz=__min(sz,save.GetLength()); + wcsncpy(wbuff,save.GetString(),minsz); + return wbuff; + } + + /// Function unlocks internal buffer + /** parameter sz specifies final lenght of string in buffer. Default + value -1 forces function calc size by own + */ + void UnlockBuffer(int sz=-1) + { + if (_ref==NULL) return; + wchar_t *wbuff=const_cast(_ref->GetStringFromMemBlock()); + if (sz<0) sz=wcslen(wbuff); + else wbuff[sz]=0; + if (sz!=(signed)_ref->GetLength()) + { + _ref->RecalcLength(); + WStringMemory::UnlockProxy(_ref); + } + } + + class WStringAtCharHelper + { + WString &_str; + size_t _index; + public: + WStringAtCharHelper(WString &str,size_t index):_str(str),_index(index) {} + WString &operator=(wchar_t z) + { + wchar_t *buff=_str.LockBuffer(); + assert(buff && _index<_str.GetLength()); + buff[_index]=z; + _str.UnlockBuffer(); + return _str; + } + operator wchar_t() + { + assert(_index<_str.GetLength()); + return ((const wchar_t *)_str)[_index]; + } + }; + + /// Function will return helper object, which can access single character in string + /** + Using array operator is slower than accessing characters by LockBuffer function + */ + WStringAtCharHelper operator[](int index) + { + return WStringAtCharHelper(*this,index); + } + + int Find(wchar_t z,size_t from=0) const + { + if (from>=GetLength()) return -1; + const wchar_t *res=wcschr(GetString()+from,z); + if (res) return res-GetString(); + else return -1; + } + + int FindLast(wchar_t z) const + { + const wchar_t *res=wcsrchr(GetString(),z); + if (res) return res-GetString(); + else return -1; + } + + int Find(const wchar_t *z,size_t from=0) const + { + if (z==NULL) return -1; + if (from>=GetLength()) return -1; + const wchar_t *res=wcsstr(GetString()+from,z); + if (res) return res-GetString(); + else return -1; + } + + int FormatV(wchar_t *format, va_list lst); + + int Format(wchar_t *format, ...); + + ///Scans string for format + /** function is limited, item count is limited up to 20 items */ + int ScanStringV(const wchar_t *format, va_list lst) const; + + ///Scans string for format + /** function is limited, item count is limited up to 20 items */ + int ScanString(const wchar_t *format, ...) const; + + bool ReplaceOnce(const WString &findWhat,const WString &replaceWith); + + bool ReplaceAll(const WString &findWhat,const WString &replaceWith); + + WString TrimLeft() const; + + WString TrimRight() const; + + WString TrimLeft(wchar_t *trimChars) const; + + WString TrimRight(wchar_t *trimChars) const; + + ///Function splits string into two + /** Left part of string is returned. + Right part of string is leaved in object + @param splitPos split position. + @return if splitPos==0, function returns empty string. if splitPos>=length, function + moves string from object to result*/ + WString Split(size_t splitPos) + { + WString result=Left(splitPos); + *this=Right(splitPos); + return result; + } + + bool IsEmpty() const {return _ref==NULL;} + + void Empty() const {_ref->Release();_ref=NULL;} + + int Compare(const wchar_t *other) const + { + return wcscmp(*this,other); + } + + bool operator>(const WString &other) const {return Compare(other)>0;} + bool operator<(const WString &other) const {return Compare(other)<0;} + bool operator>=(const WString &other) const {return Compare(other)>=0;} + bool operator<=(const WString &other) const {return Compare(other)<=0;} + bool operator!=(const WString &other) const {return Compare(other)<=0;} + bool operator==(const WString &other) const {return Compare(other)<=0;} + + WString Upper() const; + WString Lower() const; + WString Reverse() const; + + ///Applies user effect on string + /** pointer should be static allocated object, or must be valid during lifetime of resulting string */ + WString Effect(IWStringEffect *effect) const; + + void SetUTF7(const char *utf7); + void SetUTF8(const char *utf8); + + ///Function converts string to SingleByte string + /** + @param codePage Platform depends code page of result + @param holder Object that holds result. Result pointer is valid during lifetime of holder. Once holder + released, pointer is invalidated. You can get resulting pointer anytime from holder reintepreting + wchar_t to char + @result pointer to string + */ + const char *AsSBString(unsigned int codePage, WString &holder); + + ///Returns multibyte string in UTF7 codepage + /**See AsSBString description*/ + const char *AsUTF7(WString &holder); + + ///Returns multibyte string in UTF7 codepage + /**See AsSBString description*/ + const char *AsUTF8(WString &holder); + + + ///Function reads string from stream + /** + Function calls streamReader repeatly until function returns zero. In each call, streamReader returns + number of characters, that has been readed. + @param sreamReader pointer to function which provides reading from a stream + @param context user defined context pointer (most in cases, pointer to stream is passed) + @param buffer space allocated for data readed from stream + @param bufferLen maximum count of characters can be written to buffer + @return streamReader returns number of characters, that has been written to buffer. Function must return zero + to stop reading + */ + void ReadFromStream(size_t (*streamReader)(wchar_t *buffer, size_t bufferLen, void *context),void *context); + + WString operator() (int from) const {return from<0?RightR(-from):Right(from);} + WString operator() (int from, int to) const + { + if (from>=0) + return to<0?Mid(from,-to):Mid(from,to-from); + else + return to<0?Mid(GetLength()+from,-to):Mid(GetLength()+from,GetLength()-from-to); + } + + ///Enables global string sharing. + /** Function Share allows share strings that contains same text. It can reduce memory + usage. Function is useful when there is many objects that contains string with same text. + + Basically, two strings is shared, if one string is created as copy of another string. Strings + is sharing they content, until one of them is modified. + + Calling Share function, string is registered for global sharing. If string with same content is already + registered, then content of current string is released, and string is shared. + + To successfully share two strings, both strings must call Share() function. Sharing is provided until one + of strings is modified. After modifications are done, Share function of modified string must be called again. + + Remember: Global sharing can reduce amount of memory, if there are multiple strings that containging + the same content. But sharing of each unique string takes small piece of memory to store sharing + informations. + + To share string automatically, use WSharedString class + WSC strings cannot be shared! + */ + void Share() const + { + WStringProxy *curref=_ref; + GetString(); + _ref=WStringMemory::ShareString(curref); + _ref->AddRef(); + curref->Release(); + } + + ///Disables global string sharing + /** Function unregisters string from global sharing database. If string is shared, function doesn't break + it. But all strings that currently sharing content will not be shared with newly created strings. + */ + void Unshare() + { + WStringMemory::UnshareString(_ref); + } +}; + +///Function will create constant WString +/** function will not copy content of string. Only creates reference to string + Using WStringConst is faster for strings in code +@exmple result=a+WStringConst(L"text")+b; +*/ +const WString WStringConst(const wchar_t *text); + +///Macro to easy convert incode string to WString +/** +function also marks text wide. +@example WString text=WSC("Hello world"); +*/ +#define WSC(x) WStringConst(L##x) +///Macro to easy convert any wchar_t buffer to constant WString +/** +IMPORTANT NOTE!: Buffer must exists until string is rendered. +If you are using WSCB in function, don't forget call GetString before function exits +If you are excepting additional string operations outside function, using standard +WString conversion can be more effecient. +*/ +#define WSCB(x) WStringConst(x) + + + +class WSharedString: public WString +{ +public: + WSharedString() {} + + ///constructs string. + explicit WSharedString(const wchar_t *string):WString(string) {Share();} + + ///constructs string from wide-char array with specified length + WSharedString(const wchar_t *string, size_t sz):WString(string,sz) {Share();}; + + ///copy constructor + /**constructor doesn't copy the string, only reference. + String is shared until it is changed + */ + WSharedString(const WSharedString &other):WString(other) {} + WSharedString(const WString &other):WString(other) {Share();} + + ///constructs string from multi-byte string. codePage specified code page of string + WSharedString(const char *sbstring, unsigned int codePage):WString(sbstring,codePage) {Share();} + + ///assignment operator + /** assignment operator doesn't copy the string only reference. + String is shared until it is changed */ + WSharedString &operator=(const WString &other) + {WString::operator =(other);Share();return *this;} + + const wchar_t *GetString() const + { + const wchar_t *res=WString::GetString(); + Share(); + return res; + } + operator const wchar_t *() const {return GetString();} + wchar_t operator[](int index) const + { + assert(index<=(int)GetLength() && index>=0); + return GetString()[index]; + } + + void UnlockBuffer(int sz=-1) + { + WString::UnlockBuffer(sz); + Share(); + } + +}; + + +#endif // !defined(AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.cpp b/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.cpp new file mode 100644 index 0000000..947ed02 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.cpp @@ -0,0 +1,397 @@ +// WStringMemorySingleThread.cpp: implementation of the WStringMemory class. +// +////////////////////////////////////////////////////////////////////// + +#include +#include +#include "WStringMemory.h" +#include "WStringProxy.h" +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +#ifdef _MT //multithreading +#define WSTRING_MT +#endif + +#ifdef WSTRING_MT //multithreading + + +struct WStringMTLock +{ + WStringProxy *_lockProxy; + LONG _recursionCount; + DWORD _owner; + HANDLE _event; + WStringMTLock(WStringProxy *x):_lockProxy(x) {} + WStringMTLock():_lockProxy(NULL) {} + + bool operator==(const WStringMTLock &other) const {return _lockProxy==other._lockProxy;} + bool operator!=(const WStringMTLock &other) const {return _lockProxy!=other._lockProxy;} + bool operator>=(const WStringMTLock &other) const {return _lockProxy>=other._lockProxy;} + bool operator<=(const WStringMTLock &other) const {return _lockProxy<=other._lockProxy;} + bool operator>(const WStringMTLock &other) const {return _lockProxy>other._lockProxy;} + bool operator<(const WStringMTLock &other) const {return _lockProxy *GLockDB=NULL; //Lock proxy database + +static void exitMT() +{ + DeleteCriticalSection(&GLocker); +} + + +static void OnStartup() +{ + InitializeCriticalSection(&GLocker); + atexit(exitMT); +} + +#define ON_STARTUP_PRIORITY_NORMAL OnStartup +#include + +#endif + + + +#define WS_MAXFREELISTS 32 +#define WS_FREELISTSTEP 32 +#define WS_TOTALMAXFREEKBYTES 256 + +#define WS_MAXIMUMFASTALLOC (WS_MAXFREELISTS*WS_FREELISTSTEP) + +#define WS_MAXFREEBYTES PerSlotMaxAlloc + + +static size_t PerSlotMaxAlloc=(WS_TOTALMAXFREEKBYTES*1024/WS_MAXFREELISTS); +static WStringProxy *FreeList=NULL; +static void **StringFreeList[WS_MAXFREELISTS]; +static size_t StringFreeBytes[WS_MAXFREELISTS]; +static bool InitManager=true; + + +static void InitManagerPointers() +{ + memset(StringFreeList,0,sizeof(StringFreeList)); + memset(StringFreeBytes,0,sizeof(StringFreeBytes)); + InitManager=false; +} + +static void *AllocStringBlock(size_t sz) +{ + if (InitManager) InitManagerPointers(); + if (sz>WS_MAXIMUMFASTALLOC) return malloc(sz); + int pos=(sz+WS_FREELISTSTEP-1)/WS_FREELISTSTEP; + void **nxt=StringFreeList[pos]; + if (nxt==0) + { + printf("malloc %d\n",pos*WS_FREELISTSTEP); + return malloc(pos*WS_FREELISTSTEP); + } + printf("fast_alloc %d\n",pos*WS_FREELISTSTEP); + StringFreeList[pos]=(void **)(*nxt); + StringFreeBytes[pos]-=_msize(nxt); + return nxt; +} + +static void DeallocStringBlock(void *ptr) +{ + size_t sz=_msize(ptr); + if (sz>WS_MAXIMUMFASTALLOC) {free(ptr);return;} + int pos=(sz+WS_FREELISTSTEP-1)/WS_FREELISTSTEP; + if (sz+StringFreeBytes[pos]>WS_MAXFREEBYTES) + { + printf("free %d\n",sz); + free(ptr);return; + } + void **proxy=(void **)ptr; + *proxy=(void *)StringFreeList[pos]; + StringFreeList[pos]=proxy; + StringFreeBytes[pos]+=sz; + printf("fast_free %d\n",sz); +} + + +static inline void *operator new(size_t alloc,size_t sz) +{ + return AllocStringBlock(sz+alloc); +} + +static inline void operator delete(void *p,size_t alloc) +{ + DeallocStringBlock(p); +} + +static inline void *operator new(size_t sz,void *ptr) +{ + return ptr; +} + +static inline void operator delete(void *ptr,void *p) +{ +} + +WStringProxy * WStringMemory::AllocString(const wchar_t *text, size_t size) +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + assert(size!=0 || text!=0); + if (size==0) size=wcslen(text); + WStringProxy *proxy=new((size+1)*sizeof(wchar_t)) WStringProxy(size,0,0); + wchar_t *alloctext=const_cast(proxy->GetStringFromMemBlock()); + if (text) wcsncpy(alloctext,text,size); + alloctext[size]=0; + if (proxy->_redirect==0) + { + proxy->_redirect=alloctext; + proxy->_blockData2=1; + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return proxy; +} + +WStringProxy * WStringMemory::AllocProxy(const WStringProxy &templateProxy) +{ + WStringProxy * res; +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + if (FreeList==NULL) res=new WStringProxy(templateProxy); + else + { + WStringProxy *alloc=FreeList; + FreeList=alloc->_baseString; + res=new((void *)alloc) WStringProxy(templateProxy); + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return res; +} + +void WStringMemory::FreeProxy(WStringProxy *proxy) +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + if (proxy->_operation==proxy->OpMemBlck && !(proxy->_blockData2==0 && proxy->_redirect!=NULL)) + { + if (proxy->_blockData2==2) UnshareString(proxy); + DeallocStringBlock(proxy); + } + else + { + proxy->~WStringProxy(); + proxy->_baseString=FreeList; + FreeList=proxy; + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif +} + +#ifdef WSTRING_MT + +void WStringMemory::LockProxy( WStringProxy *proxy) +{ +nextTry: + EnterCriticalSection(&GLocker); + WStringMTLock srch(proxy),*found; + if (GLockDB==NULL) GLockDB=new BTree(16); + found=GLockDB->Find(srch); + if (found==NULL) + { + srch._event=NULL; + srch._owner=GetCurrentThreadId(); + srch._recursionCount=1; + GLockDB->Add(srch); + } + else + { + if (found->_owner!=GetCurrentThreadId()) + { + HANDLE w=found->_event; + if (w==0) {w=found->_event=CreateEvent(NULL,TRUE,FALSE,NULL);} + LeaveCriticalSection(&GLocker); //leave section + WaitForSingleObject(w,INFINITE); + goto nextTry; + } + else + { + found->_recursionCount++; + } + } + LeaveCriticalSection(&GLocker); //leave section +} + +void WStringMemory::UnlockProxy( WStringProxy *proxy) +{ + EnterCriticalSection(&GLocker); + WStringMTLock srch(proxy),*found; + found=GLockDB->Find(srch); + if (found) + { + if (--found->_recursionCount==0) + { + if (found->_event!=NULL) + { + SetEvent(found->_event); + CloseHandle(found->_event); + } + GLockDB->Remove(*found); + } + } + LeaveCriticalSection(&GLocker); +} + + +void WStringMemory::AddRefProxy(WStringProxy *proxy) +{ + InterlockedIncrement(reinterpret_cast(&proxy->_refCount)); +} + +bool WStringMemory::ReleaseRefProxy(WStringProxy *proxy) +{ + LONG res=InterlockedDecrement(reinterpret_cast(&proxy->_refCount)); + if (res<0) res=InterlockedIncrement(reinterpret_cast(&proxy->_refCount)); + return res==0; +} + +#else +void WStringMemory::LockProxy( WStringProxy *proxy) +{ + //not needed in single thread environment +} + +void WStringMemory::UnlockProxy( WStringProxy *proxy) +{ + //not needed in single thread environment +} + + +void WStringMemory::AddRefProxy(WStringProxy *proxy) +{ + //no special handling in single thread environment + ++proxy->_refCount; +} + +bool WStringMemory::ReleaseRefProxy(WStringProxy *proxy) +{ + //no special handling in single thread environment + if (proxy->_refCount) --proxy->_refCount; + return proxy->_refCount==0; +} + +#endif +void WStringMemory::FreeExtra() +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + while (FreeList) + { + void *proxy=FreeList; + FreeList=FreeList->_baseString; + free(proxy); + } + for (int i=0;i_redirect,other._str->_redirect); + } + + bool operator==(const ShareDBItem& other) const {return Compare(other)==0;} + bool operator>=(const ShareDBItem& other) const {return Compare(other)>=0;} + bool operator<=(const ShareDBItem& other) const {return Compare(other)<=0;} + bool operator!=(const ShareDBItem& other) const {return Compare(other)!=0;} + bool operator>(const ShareDBItem& other) const {return Compare(other)>0;} + bool operator<(const ShareDBItem& other) const {return Compare(other)<0;} +}; + +static BTree *GDB=NULL; + +WStringProxy *WStringMemory::ShareString(WStringProxy *proxy) +{ + if (proxy->_operation!=WStringProxy::OpMemBlck || proxy->_blockData2==0 || proxy->_blockData2==2) return proxy; + +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + + if (GDB==NULL) GDB=new BTree; + + proxy->_blockData2=2; //block is subject of sharing + proxy->_redirect=proxy->GetStringFromMemBlock(); //setup pointer to string + ShareDBItem *found=GDB->Find(ShareDBItem(proxy)); + if (found) {proxy->_blockData2=1;proxy=found->_str;} + else GDB->Add(ShareDBItem(proxy)); +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return proxy; +} + +void WStringMemory::UnshareString(WStringProxy *proxy) +{ + if (proxy->_operation!=WStringProxy::OpMemBlck || proxy->_blockData2!=2) return; + if (GDB==NULL) return; +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + GDB->Remove(ShareDBItem(proxy)); + proxy->_blockData2=1; +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif +} \ No newline at end of file diff --git a/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.h b/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.h new file mode 100644 index 0000000..a81b08e --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WStringMemory.h @@ -0,0 +1,61 @@ +// WStringMemory.h: interface for the WStringMemory class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_) +#define AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_ + +#include + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class WStringProxy; + +class WStringMemory +{ +public: + + static WStringProxy * AllocString(const wchar_t *text, size_t size); + static WStringProxy * AllocProxy(const WStringProxy &templateProxy); + static void FreeProxy(WStringProxy *proxy); + static void LockProxy(WStringProxy *proxy); + static void UnlockProxy(WStringProxy *proxy); + + //Releases extra memory leaved for future fast allocations + static void FreeExtra(); + + //Support addref for proxy - Single- or Multi- thread support + static void AddRefProxy(WStringProxy *proxy); + + //Support addref for proxy - Single- or Multi- thread support + //returns true, when counter reached zero + static bool ReleaseRefProxy(WStringProxy *proxy); + + ///Gets statistics about memory manager + /** + @param details optional pointer to 32 size_t items. Array will be filled + with sizes of each string fastalloc group. + @return function returns total bytes allocated for string fast allocation. + (This number should be below 256KB) + */ + static size_t GetStatistics(size_t *details=NULL); + + ///Function allows sharing the strings + /** This function is called by WString::Share function + Function mark proxy shared. If string is same as shared, + it returns pointer to proxy with proxy of string that contains + the same text. + Read description of WString::Share for more informations + */ + static WStringProxy *ShareString(WStringProxy *proxy); + + ///Function disables sharing of the string + static void UnshareString(WStringProxy *proxy); + +}; + + + +#endif // !defined(AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.cpp b/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.cpp new file mode 100644 index 0000000..6b93900 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.cpp @@ -0,0 +1,185 @@ +// WStringProxy.cpp: implementation of the WStringProxy class. +// +////////////////////////////////////////////////////////////////////// + + +#include "WStringProxy.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +/** Funkce vytvoří transitivní uzávěr. +to znamená, že zruší všechny zřetězené redirecty. +*/ +WStringProxy *WStringProxy::TransitivniUzaver() +{ + if (_operation==OpSubstr && _offset==0 && _stringSize==_baseString->GetLength()) + { + WStringProxy *next=_baseString->TransitivniUzaver(); + if (next==NULL) return this; + next->AddRef(); + _baseString->Release(); + _baseString=next; + return next; + } + return NULL; +} + +/** Main render procedure +It creates allocates buffer proxy and renders tree into it +Then turns self into redirect proxy a redirect self into newly created string +Rerurns pointer to newly created proxy +*/ +WStringProxy *WStringProxy::RenderString() +{ + if (_operation==OpMemBlck) return this; + + WStringProxy *pp=TransitivniUzaver(); + if (pp!=NULL) return pp->_baseString->RenderString(); + + WStringProxy *newProxy=WStringMemory::AllocString(NULL,_stringSize); + wchar_t *renderPtr=const_cast(newProxy->GetStringFromMemBlock()); + + RenderStringToBuffer(renderPtr); + + newProxy->AddRef(); + this->~WStringProxy(); + _operation=OpSubstr; + _offset=0; + _baseString=newProxy; + + return newProxy; +} + +/** Function renders simple effect into buffer +Function needs buffer with nul terminated string +*/ +void WStringProxy::RenderSimpleEffect(wchar_t *renderPtr) +{ + assert(_operation==OpEffect); + switch (_effect) + { + case EfLower: wcslwr(renderPtr);break; + case EfUpper: wcsupr(renderPtr);break; + case EfReverse: wcsrev(renderPtr);break; + } + +} + +/** Light phase of rendering. Used to render string that is not +created from substring. This part is optimized for concat and user effects +When substring must be rendered, function call RenderStringToBufferSubstr to +render substring. +*/ +void WStringProxy::RenderStringToBuffer(wchar_t *renderPtr) +{ + WStringMemory::LockProxy(this); + switch (_operation) + { + case OpConcat: + _baseString->RenderStringToBuffer(renderPtr); + _secondString->RenderStringToBuffer(renderPtr+_baseString->GetLength()); + break; + case OpSubstr: + { + _baseString->RenderStringToBufferSubstr(renderPtr,_offset,GetLength()); + } + break; + case OpMemBlck: + { + const wchar_t *str=GetStringFromMemBlock(); + wcsncpy(renderPtr,str,_stringSize); + } + break; + case OpEffect: + { + unsigned long offset=0; + renderPtr[_stringSize]=0; //we can append zero, because right side of string is not yet rendered + //if this is end of string, one extra character for zero is also allocated. + //efect functions can rely on it. + if (_blockData2>=256) offset=_userEffect->PreRenderString(renderPtr,_baseString->GetLength()); //call prerender to prepare begin of buffer + _baseString->RenderStringToBuffer(renderPtr+offset); //render string to rest of buffer + if (_blockData2>=256) _userEffect->RenderString(renderPtr,_baseString->GetLength()); //apply effect to buffer + else RenderSimpleEffect(renderPtr); + } + break; + }; + WStringMemory::UnlockProxy(this); +} + +/** +Deep phase of rendering. Function can render substrings, or render substring of two +concated strings. Function can also perform partial effect on string. Function cannot +handle partial user effect, so this effects are converted to things strings. +*/ +void WStringProxy::RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size) +{ + WStringMemory::LockProxy(this); + switch (_operation) + { + case OpConcat: + { + //process substring of concat + //count characters in buffer + size_t rendered; + //when string starts in left string + if (_baseString->GetLength()>offset) + { + //calculate total characters that may be rendered + rendered=_baseString->GetLength()-offset; + //but limit it to request size + if (rendered>size) rendered=size; + //render substring into buffer + _baseString->RenderStringToBufferSubstr(renderPtr,offset,rendered); + } + else + //no character has been rendered + rendered=0; + + //there is still characters remained to render. We will take it from second string + if (size-rendered>0) + { + if (offset>_baseString->GetLength()) offset-=_baseString->GetLength(); + else offset=0; + _secondString->RenderStringToBufferSubstr(renderPtr+rendered,offset,size-rendered); + } + } + break; + case OpSubstr: + { //rendering substrings is very easy + offset+=_offset; //add offset of substring + assert(offset+size<=GetLength()); //check length + //render substring + this->RenderStringToBufferSubstr(renderPtr,offset,size); + } + break; + case OpMemBlck: + { + //rendering from memory, final stop in recursion + //Get pointer string + const wchar_t *str=GetStringFromMemBlock(); + //copy substring from string into render buffer + wcsncpy(renderPtr,str+offset,size); + } + break; + case OpEffect: + if (_blockData2>=256) //interface cannot handle partial rendering + { + RenderString(); //convert proxy to simple redirect and render it + RenderStringToBufferSubstr(renderPtr,offset,size); //now we are able to cut out part + } + else + { + //all standard effects maps string 1:1 + //first get content of substring into buffer + _baseString->RenderStringToBufferSubstr(renderPtr,offset,size); + //we can append zero, because right side of string is not yet rendered + renderPtr[size]=0; + //process effect on target + RenderSimpleEffect(renderPtr); + } + break; + }; + WStringMemory::UnlockProxy(this); +} \ No newline at end of file diff --git a/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.h b/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.h new file mode 100644 index 0000000..e5f470b --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/WStringProxy.h @@ -0,0 +1,232 @@ +// WStringProxy.h: interface for the WStringProxy class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) +#define AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WStringMemory.h" +#include "IWStringEffect.h" +#include +#include +#include +#include + +/* +List of proxy types + +Memory_Proxy _operation=OpMemBlck + _blockData==0 and _blockData2==0 + or + _blockData!=0 and _blockData2!=0 + (_redirect - debug pointer) + (_blockData - 1) + +Proxy_Const _operation=OpMemBlck + _redirect - pointer to string + _blockData2=0 + +Proxy_Shared _operation=OpMemBlck + _redirect - pointer to string + _blockData2=2; + +Proxy_Immediate _operation=OpMemBlck + _blockData>0xFFFF + _blockData2>0xFFFF + both parameters are used by immediate memory manager + +Proxy_Concat _operation=OpConcat + _baseString and _secondString is valid + +Proxy_Link _operation=OpSubstr + _baseString is valid + _stringSize==_baseString->_stringSize + _offset==0; + NOTE: Can be used without rendering + +Proxy_RightSub _operation=OpSubstr + _baseString is valid + _offset<=_baseString->_stringSize + _stringSize==_baseString->_stringSize-_offset + NOTE: Can be used without rendering + +Proxy_SubString _operation=OpSubstr + _baseString is valid + _offset<=_baseString->_stringSize + _stringSize<=_baseString->_stringSize-_offset + +Proxy_Effect _operation=OpEffect + _baseString is valid + _stringSize=_baseString->_stringSize + _effect defining effect code < 0xFFFF + +Proxy_UserEffect _operation=OpEffect + _baseString is valid + _stringSize=_baseString->_stringSize + _effect>0xFFFF + _userEffect defining pointer to effect interface + +*/ +class WStringProxy +{ +public: + enum Operation + { + OpConcat=0, //proxy contains two links to concat it + OpSubstr=1, //proxy contains link to another proxy and specified substring + OpMemBlck=-2, //proxy contains informations about following string + OpEffect=-1, //proxy describing some efect with string + }; + + enum Effect + { + EfLower, //effect lower case + EfUpper, //effect upper case + EfReverse, //effect reverse string + }; +public: + + unsigned long _refCount; //reference count + unsigned long _stringSize:30; //string size in characters (maximum size 1073741823 characters ~ 2147483646 bytes) + Operation _operation:2; //operation with string or proxy type + + union + { + WStringProxy *_baseString; //pointer to next proxy referenced by this proxy + unsigned long _blockData; //user defined block data for OpMemBlock proxy type + const wchar_t *_redirect; //used for OpMemBlock, when _blockData2 is zero. + }; + + union + { + WStringProxy *_secondString; //pointer to second string for OpConcat + unsigned long _offset; //offset of substring for OpSubstr + Effect _effect; //effect selector for OpEffect + IWStringEffect *_userEffect; //user effect defined by IWStringEffect interface (valid when _effect is invalid) + unsigned long _blockData2; //user defined block data for OpMemBlock proxy type - exception: if this value is zero, member _redirect is valid + + }; + + + void RenderStringToBuffer(wchar_t *renderPtr); + void RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size); + WStringProxy *TransitivniUzaver(); + void RenderSimpleEffect(wchar_t *renderPtr); + +public: + WStringProxy():_refCount(0),_operation(OpSubstr),_stringSize(0),_baseString(0),_secondString(0) {} //inicializes empty string proxy + + WStringProxy(WStringProxy *other): + _refCount(0), + _stringSize(other->GetLength()), + _baseString(other), + _operation(OpSubstr), + _offset(0) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *other, unsigned long offset, unsigned long size): + _refCount(0), + _stringSize(size), + _baseString(other), + _operation(OpSubstr), + _offset(offset) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *a, WStringProxy *b): + _refCount(0), + _stringSize(a->GetLength()+b->GetLength()), + _baseString(a), + _operation(OpConcat), + _secondString(b) + {_baseString->AddRef();_secondString->AddRef();} + + WStringProxy(WStringProxy *a, Effect effect): + _refCount(0), + _stringSize(a->GetLength()), + _baseString(a), + _operation(OpEffect), + _effect(effect) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *a, IWStringEffect *userEffect): + _refCount(0), + _stringSize(a->GetLength()+userEffect->GetEffectExtraSize(a->GetLength())), + _baseString(a), + _operation(OpEffect), + _userEffect(userEffect) + {_baseString->AddRef();} + + WStringProxy(unsigned long size, unsigned long user1, unsigned long user2): + _refCount(0), + _stringSize(size), + _operation(OpMemBlck), + _blockData(user1), + _blockData2(user2) + {} + + WStringProxy(const wchar_t *imText): + _refCount(0), + _stringSize(wcslen(imText)), + _redirect(imText), + _blockData2(0), + _operation(OpMemBlck) + {} + + WStringProxy(const WStringProxy &other) + { + memcpy(this,&other,sizeof(*this)); + if (_operation!=OpMemBlck) _baseString->AddRef(); + if (_operation==OpConcat) _secondString->AddRef(); + } + + WStringProxy& operator=(const WStringProxy &other) + { + WStringProxy::~WStringProxy(); //call destructor to destruct current proxy + memcpy(this,&other,sizeof(*this)); //construct new proxy from template + if (_operation!=OpMemBlck) _baseString->AddRef(); + if (_operation==OpConcat) _secondString->AddRef(); + } + + WStringProxy *RenderString(); + + ~WStringProxy() + { + if (_operation!=OpMemBlck) _baseString->Release(); + if (_operation==OpConcat) _secondString->Release(); + } + + + unsigned long GetLength() {return _stringSize;} + void AddRef() {if (this) WStringMemory::AddRefProxy(this);} + void Release() {if (this) if (WStringMemory::ReleaseRefProxy(this)) WStringMemory::FreeProxy(this);} + + const wchar_t *GetString() + { + if (_operation==OpMemBlck) return (const wchar_t *)(this+1); + WStringProxy *p=RenderString(); + (*this)=*p; + return (const wchar_t *)(p+1); + } + + const wchar_t *GetStringFromMemBlock() + { + assert(_operation==OpMemBlck); + if (_blockData2==0 && _redirect!=NULL) return _redirect; + else return (const wchar_t *)(this+1); + } + + bool IsShared() {return _refCount>1;} + + void RecalcLength() + { + const wchar_t *str=GetStringFromMemBlock(); + _stringSize=wcslen(str); + } + +}; + +#endif // !defined(AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) diff --git a/DDLReader/Projects/Skeldal/DDLReader/res/DDLReader.ico b/DDLReader/Projects/Skeldal/DDLReader/res/DDLReader.ico new file mode 100644 index 0000000..7eef0bc Binary files /dev/null and b/DDLReader/Projects/Skeldal/DDLReader/res/DDLReader.ico differ diff --git a/DDLReader/Projects/Skeldal/DDLReader/resource.h b/DDLReader/Projects/Skeldal/DDLReader/resource.h new file mode 100644 index 0000000..2625141 --- /dev/null +++ b/DDLReader/Projects/Skeldal/DDLReader/resource.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DDLReader.rc +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_DDLREADER_DIALOG 102 +#define IDS_FILEOPENFAILED 102 +#define IDC_HEADGROUP 103 +#define IDC_HEADFNAME 104 +#define IDC_HEADSIZE 105 +#define IDC_HEADOFFSET 106 +#define IDS_DDLFILTER 107 +#define IDC_GROUP_GRAPHICS 108 +#define IDC_GROUP_SOUNDS 109 +#define IDC_GROUP_FONTS 110 +#define IDC_GROUP_BASIC 111 +#define IDC_GROUP_ITEMS 112 +#define IDC_GROUP_MONSTERS 113 +#define IDC_GROUP_DIALOGS 114 +#define IDC_GROUP_UNSPECIFIED 115 +#define IDC_GROUP_UNKNOWN 116 +#define IDS_UNABLETOCREATEFILE 117 +#define IDS_UNABLETOEXTACTDATA 118 +#define IDR_MAINFRAME 128 +#define IDD_PROGRESS 129 +#define IDD_EXPORTING 129 +#define IDC_FILELIST 1001 +#define IDC_FOLDER 1002 +#define IDC_BROWSE 1003 +#define IDC_EXPORT 1004 +#define IDC_POPISEK 1005 +#define IDC_DDLFILE 1006 +#define IDC_DDLBROWSE 1007 +#define IDC_PROGRESS 1008 +#define IDC_NAME 1009 +#define IDC_BUTTON1 1010 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/DDLReader/StdAfx.cpp b/DDLReader/StdAfx.cpp new file mode 100644 index 0000000..1a90873 --- /dev/null +++ b/DDLReader/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// DDLReader.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/DDLReader/StdAfx.h b/DDLReader/StdAfx.h new file mode 100644 index 0000000..666c5f5 --- /dev/null +++ b/DDLReader/StdAfx.h @@ -0,0 +1,27 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_) +#define AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include "wstring.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__C5BDACC6_729E_4CA2_B27E_A1F209FB32A7__INCLUDED_) diff --git a/DDLReader/WPathname.cpp b/DDLReader/WPathname.cpp new file mode 100644 index 0000000..fab2f57 --- /dev/null +++ b/DDLReader/WPathname.cpp @@ -0,0 +1,408 @@ +// WPathname.cpp: implementation of the WPathname class. +// +////////////////////////////////////////////////////////////////////// + +#include "WPathname.h" +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +WPathname::WPathname(const wchar_t *name /*=NULL*/) +{ + if (name) SetPathname(name); +} + +WPathname::WPathname(const WString &name) +{ + SetPathname(name); +} + +WPathname::WPathname(const wchar_t *relpath, const WPathname &abspath) +{ + _fullpath=WString(relpath); + int chr=_fullpath.FindLast('\\'); + if (chr!=-1) + { + _path=_fullpath.Left(chr+1); + _filetitle=_fullpath.Right(chr+1); + } + else + { + _filetitle=_fullpath; + } + chr=_filetitle.FindLast('.'); + if (chr!=-1) + { + _extension=_filetitle.Right(chr); + _filetitle=_filetitle.Left(chr); + } + + RelativeToFull(abspath); +} + + +WPathname::WPathname(const WPathname &other) +{ + _fullpath=other._fullpath; + _path=other._path; + _filetitle=other._filetitle; + _extension=other._extension; +} + +void WPathname::SetDrive(wchar_t dr) +{ + if (HasDrive()) + { + if (dr==0) _path=_path.Right(2); + else _path[0]=dr; + } + else if (dr!=0) + { + int np=IsNetworkPath(); + wchar_t buff[2]; + buff[0]=dr; + buff[1]=':'; + buff[2]=0; + if (np) + _path=WString(buff)+_path.Right(np); + else + _path=WString(buff)+_path; + + } + RebuildPath(); +} + +void WPathname::SetDirectory(const wchar_t *dir) +{ + bool copydrv; //directory doesn't contain drive, need copy from original + bool addslash; //directory doesn't ending by backslash, need add it + + int len=wcslen(dir); + copydrv=HasDrive(dir) || !HasDrive(); //copy original drive, if exists and directory doesn't contaion drive + if (wcsncmp(dir,L"\\\\",2)==0) copydrv=true; //network path, don't copy drive + addslash=len && dir[len-1]!='\\'; //add slash + if (copydrv) + _path=WString(dir); + else + _path=_path.Left(2)+WString(dir); + if (addslash) + _path+=WSC("\\"); + + RebuildPath(); +} + +void WPathname::SetFilename(const wchar_t *filename) +{ + WString wfilename=WString(filename); + int dot=wfilename.FindLast('.'); + if (dot==-1) + { + _filetitle=wfilename; + _extension=0; + } + else + { + _filetitle=wfilename.Left(dot); + _extension=wfilename.Right(dot); + } + + RebuildPath(); +} + +void WPathname::SetExtension(const wchar_t *ext) +{ + _extension=WString(ext); + RebuildPath(); +} + +void WPathname::SetFileTitle(const wchar_t *title) +{ + _filetitle=WString(title); + RebuildPath(); +} + +void WPathname::SetPathname(const wchar_t *pathname) +{ + SetPathname(WString(pathname)); +} + +void WPathname::SetPathname(const WString &pathname) +{ + if (pathname.GetLength()==0) SetNull(); + else + { + wchar_t *part; + DWORD needsz=GetFullPathNameW(pathname,0,NULL,&part); + wchar_t *fpth=(wchar_t *)alloca(needsz*sizeof(*fpth)); + GetFullPathNameW(pathname,needsz,fpth,&part); + part=wcsrchr(fpth,'\\'); + if (part) part++;else part=NULL; + if (part) + { + SetFilename(part); + *part=0; + } + else + SetFilename(WString()); + SetDirectory(fpth); + } +} + +const wchar_t *WPathname::GetNameFromPath(const wchar_t *path) +{ + const wchar_t *c=wcsrchr(path,'\\'); + if (c!=NULL) c++;else return path; + return c; +} + +const wchar_t *WPathname::GetExtensionFromPath(const wchar_t *path) +{ + const wchar_t *fname=GetNameFromPath(path); + const wchar_t *c=wcsrchr(fname,'.'); + if (c==NULL) c=wcsrchr(path,0); + return c; +} + +void WPathname::RebuildPath() +{ + _fullpath=_path+_filetitle+_extension; +} + +bool WPathname::GetDirectoryWithDriveWLBS(wchar_t *buff, size_t size) const +{ + size_t psize=wcslen(GetDirectoryWithDrive()); + if (psize>size) return false; + if (psize==0) {buff[0]=0;return true;} + wcsncpy(buff,GetDirectoryWithDrive(),psize-1); + buff[psize-1]=0; + return true; +} + +WString WPathname::GetDirectoryWithDriveWLBS() const +{ + if (_path.GetLength()) return _path.Left(_path.GetLength()-1); + return WString(); +} + +bool WPathname::IsPathValid() const +{ + if (IsNull()) return false; + wchar_t *invalidChars=L"/*?\"<>|"; + const wchar_t *path=GetFullPath(); + if (*path==0) return false; + while (*path) + { + if (wcschr(invalidChars,*path)!=NULL) return false; + path++; + } + return true; +} + +bool WPathname::SetTempDirectory() +{ + wchar_t buff[1]; + DWORD size=GetTempPathW(1,buff); + if (size==0) return false; + WString pth; + wchar_t *p=pth.CreateBuffer(size); + if (GetTempPathW(size,p)==0) return false; + pth.UnlockBuffer(); + _path=pth; + return true; +} + +bool WPathname::SetDirectorySpecial(int nSpecCode) +{ + wchar_t buff[MAX_PATH]; + if (SHGetSpecialFolderPathW(GetForegroundWindow(),buff,nSpecCode,FALSE)!=NOERROR) return false; + SetDirectory(buff); + return true; +} + +bool WPathname::SetTempFile(const wchar_t *prefix, unsigned int unique) +{ + wchar_t tempname[MAX_PATH]; + if (GetTempFileNameW(GetDirectoryWithDrive(),prefix,unique,tempname)==0) return false; + this->SetPathname(tempname); + return true; +} + +WPathname WPathname::GetExePath() +{ + wchar_t buff[MAX_PATH*4]; + GetModuleFileNameW(NULL,buff,sizeof(buff)); + return WPathname(buff); +} + +const wchar_t *WPathname::FullToRelativeProjectRoot(const wchar_t *full, const wchar_t *projectRoot) +{ + const wchar_t *a=full,*b=projectRoot; + while (*a && towlower(*a)==towlower(*b)) {a++;b++;}; + if (*b) return full; + return a; +} + +bool WPathname::FullToRelative(const WPathname &relativeto) +{ + if (relativeto.IsNull() || IsNull()) return false; + bool h1=HasDrive(); + bool h2=relativeto.HasDrive(); + if (h1!=h2) return false; //rozdilny zpusob adresace - nelze vytvorit relatvni cestu + if (h1==true && h2==true && towupper(GetDrive())!=towupper(relativeto.GetDrive())) + return false; //ruzne disky, nelze vytvorit relativni cestu + if (wcsncmp(_path,L"\\\\",2)==0) //sitova cesta + { + int slsh=0; //citac lomitek + const wchar_t *a=_path; + const wchar_t *b=relativeto._path; + while (towupper(*a)==towupper(*b) && *a && slsh<3) //zacatek sitove cesty musi byt stejny + { + if (*a=='\\') slsh++; + a++;b++; + } + if (slsh!=3) return false; //pokud neni stejny, nelze vytvorit relativni cestu + } + int sublevel=0; + const wchar_t *ps1=_path; + const wchar_t *ps2=relativeto._path; + if (h1) {ps1+=2;ps2+=2;} + const wchar_t *sls=ps2; + while (towupper(*ps1)==towupper(*ps2) && *ps1) + { + if (*ps2=='\\') sls=ps2+1; + ps1++;ps2++; + } + ps1-=ps2-sls; + if (sls) + { + while (sls=wcschr(sls,'\\')) + { + sls++; + sublevel++; + } + } + wchar_t *buff=(wchar_t *)alloca((sublevel*3+wcslen(ps1)+1)*sizeof(*buff)); + wchar_t *pos=buff; + for (int i=0;iref._path.GetString()) + { + end--; + while (end>ref._path.GetString() && end[-1]!='\\') end--; + } + beg+=3; + } + else + beg+=2; + } + int partln=end-ref._path; + wchar_t *buff=(wchar_t *)alloca((partln+wcslen(beg)+1)*sizeof(*buff)); + wcsncpy(buff,ref._path,partln); + wcscpy(buff+partln,beg); + SetDrive(0); + SetDirectory(buff); + return true; +} + +int WPathname::IsNetworkPath() const +{ + if (wcsncmp(_path,L"\\\\",2)==0) //sitova cesta + { + const wchar_t *p=_path+2; + const wchar_t *c=wcschr(p,'\\'); + if (c) return c-_path; + } + return 0; +} + +void WPathname::SetServerName(const wchar_t *server) +{ + if (HasDrive()) SetDrive(0); + else + { + int np=IsNetworkPath(); + _path=_path.Right(np); + } + + _path=WSC("\\\\")+WString(server)+WSC("\\"); + RebuildPath(); +} + +void WPathname::SetNull() +{ + _fullpath=_path=_filetitle=_extension=0; +} + +bool WPathname::GetPartFromPath(const wchar_t *path, int partnum, wchar_t *buff, int bufsize, int mode) +{ + const wchar_t *scan=path; + while (*scan=='\\') scan++; + while (partnum && *scan) + { + while (*scan!='\\' && *scan) scan++; + while (*scan=='\\') scan++; + partnum--; + } + if (*scan==0) + { + buff[0]=0; + return false; + } + int pt=0; + if (mode==-1) + { + pt=scan-path; + if (pt>bufsize) + { + buff[0]=0; + return true; + } + else + memcpy(buff,path,pt); + } + bool nlast=false; + while (*scan && (mode==1 || !nlast) && pt 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WString.h" + +#ifndef ASSERT +#ifdef _DEBUG +#define ASSERT(x) assert(x) +#else +#define ASSERT(x) +#endif +#endif + +#define WPathnameCompare(op) bool operator op (const WPathname &other) const \ +{if (IsNull() || other.IsNull()) return false;else return wcsicmp(_fullpath,other._fullpath) op 0;}\ + bool operator op (const wchar_t *other) const \ +{ASSERT(!other || other[0]!=0);\ + if (IsNull() || other==NULL) return false;else return wcsicmp(_fullpath,other) op 0;} + +/** class WPathname simplifying manipulation with WPathnames, filenames, general paths, and +also supports convert from absolute path to relative respectively */ + + + +class WPathname +{ + ///object value and data + /**The implementation of WPathname creates only one buffer for all variables. It can + increase speed by effective memory use. Strings are stored one after another separated + by zero byte. Evry time any string changed, implementation recalculate buffer usage, and + decide, whether it should resize buffer or not. + + _fullpath also points to string contain full path with filename, + it is dominant value of the class + */ + WString _fullpath; + WString _path; /// + If name is provided, WPathname will expand it into full name with drive and folder name. + @param name optional argument to inicialize object + */ + WPathname(const wchar_t *name=NULL); + WPathname(const WString &name); + + ///Construct WPathname class + /** + @param relpath Relative path or uncomplette path or single filename with extension. + WPathname will expand this WPathname into full using absolute path provided by the second + argument. + @param abspath Absolute path used as reference to folder - the origin of relative path + provided in the first argument. + */ + WPathname(const wchar_t *relpath, const WPathname &abspath); + + ///Construct WPathname as copy of another WPathname + WPathname(const WPathname &other); + + + ///Function returns the current drive letter. + /** Before usage, ensure, that current WPathname contain drive. + In network path drive letter is missing. + In this case, result is undefined. To ensure, use HasDrive function + @return the drive letter of current path. + */ + wchar_t GetDrive() const + { + if (IsNull()) return 0; + return _path[0]; + } + + ///Static function determines, if argument contain a drive information. + /** + @param dir directory to inspect + @return true, if directory contain drive.

+ This function is independed, it don't need any WPathname variable declared. + */ + static bool HasDrive(const wchar_t *dir) + {return (dir[0]>='A' && dir[0]<='Z' || dir[0]>='a' && dir[0]<='z') && dir[1]==':';} + + ///Function determines, if current WPathname contain a drive information + /** + @return true, if current WPathname contain a drive information + */ + bool HasDrive() const + { + if (IsNull()) return false; + return HasDrive(_path); + } + + + ///Function returns current folder name + /** + if current folder name contain drive, only folder name is returned (without drive). + In other cases (relative or network drives) returns full path. + @return folder name or full path. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetDirectory() const + { + if (HasDrive()) return _path.GetString()+3; + else return _path.GetString()+IsNetworkPath(); + } + + const wchar_t *GetDirectoryWithDrive() const + { + return _path; + } + + ///Function returns current filename with extension + /** + @return current filename with extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetFilename() const + { + if (IsNull()) return NULL; + const wchar_t *blk=wcsrchr(_fullpath,'\\'); + if (blk) blk=blk+1;else blk=_fullpath; + return blk; + } + + ///Function returns current extension (with starting dot) + /** + @return current extension. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetExtension() const + {return _extension;} + + ///Function returns current filename without extension (without dot) + /** + @return current filename without extension (without dot). Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + const wchar_t *GetTitle() const + {return _filetitle;} + + ///Function changes current drive. + /**If object contain WPathname with drive, then current drive is changed and function returns. + If object contain network path, then computer name is changed to the drive name. + If object contain relative path, then whole path is replaced by path on root on drive. + @param dr new drive letter. This parameter can be set to zero. It means, that current + driver is deleted, and path is converted to relative path from root. Note: Zero c + cannot be used with network paths and relative paths, and finnaly has no effect to the object + */ + + void SetDrive(wchar_t dr); + + ///Sets new directory for object + /** if object contain a drive letter and argument dir doesn't, then current drive is remain + and only directory part is replaced. If current path is network path or relative path, + then whole path is replaced by new one. + If argument dir contain drive letter, then whole path is replaced too. + @param dir contain new WPathname. Backslash should be the last wchar_tacter in string + */ + void SetDirectory(const wchar_t *dir); + + ///Sets new filename for object. + /** + If filename contain dot, function assumes, that filename is provided with extension. + Otherwise, current extension remains untouched. + @param filename new filename for object + */ + + void SetFilename(const wchar_t *filename); + + ///Sets new extension for object. + /** + If ext doesn't starting with dot, function adds it. + @param ext new extension for object + */ + void SetExtension(const wchar_t *ext); + + ///Sets new file title + /** Function changes file title, extension remains untouched. + if title contains extension (dot inside its name), this extension doesn't change + current extension. For example, if current extension is ".cpp" and filetitle contain + "source.h", then result is "source.h.cpp" + @param title a new title for object. + */ + + void SetFileTitle(const wchar_t *title); + + ///Function returns full WPathname. + /** + @return current WPathname. Pointer is valid until any first change in object. + Do not invoke release function at pointer! + */ + + const wchar_t *GetFullPath() const + {return _fullpath;} + + ///Sets WPathname + /** Function has same effect as constructor. But it can be used + anytime during object lifetime. It simply replaces current WPathname with newer. WPathname + in argument is expanded to full WPathname, current directory is used as reference. + @param WPathname new WPathname + */ + void SetPathname(const wchar_t *pathname); + void SetPathname(const WString &pathname); + + WPathname& operator=(const wchar_t *other) + {SetPathname(other);return *this;} + + WPathname& operator=(const WString &other) + {SetPathname(other);return *this;} + + WPathname& operator=(const WPathname& other) + { + _fullpath=other._fullpath; + _path=other._path; + _filetitle=other._filetitle; + _extension=other._extension; + return *this; + } + + ///converts object to string + operator const wchar_t *() const + {return GetFullPath();} + + ///Static function to help getting filename from WPathname + /** Function finds last backslash / and return pointer to first wchar_tacter after it. + Pointer stays valid until original path is destroyed or until original path is changed + @param path WPathname to inspect as string + @return pointer to filename + */ + static const wchar_t *GetNameFromPath(const wchar_t *path); + + ///Static function to help getting extension from WPathname + /** Function finds last dot '.' in filename return pointer to it (extension with dot). + Pointer stays valid until original path is destroyed or until original path is changed + @param path WPathname to inspect as string + @return pointer to extension + */ + static const wchar_t *GetExtensionFromPath(const wchar_t *path); + + ///Function sets server name for network path + /** If current path is network path, then changes server name to newer. Otherwise + it remove drive letter, and insert server name before remain path + @param server server name without slashes + */ + void SetServerName(const wchar_t *server); + + ///Function inspects current path and returns, whether contain server name + /**@return zero, if current path is not valid network path. Nonzero if path contain + server name. Then value returned count wchar_tacters containing server name with precedent + slashes. + */ + int IsNetworkPath() const; + + ///Function converts current relative path into absolute path + /** + If current path is not relative, function do nothing. + @param ref reference to path, against which path is relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool RelativeToFull(const WPathname &ref); + + ///Function converts current absolute path into relative path + /** + If current path is not relative, function do nothing. Both paths must be on the same + drive or network computer. + + @param ref reference to path, against which path should be relative. + @return true if path has been converted, or false, if conversion is impossible + */ + bool FullToRelative(const WPathname &relativeto); + + WPathname& operator+=(const wchar_t *relativePath) + {*this=WPathname(relativePath,*this);return *this;} + + WPathname operator+(const wchar_t *relativePath) + {WPathname out(relativePath,*this);return out;} + + bool IsNull() const {return _fullpath.GetLength()==0;} + + void SetNull(); + + WPathnameCompare(<) + WPathnameCompare(>) + WPathnameCompare(==) + WPathnameCompare(>=) + WPathnameCompare(<=) + WPathnameCompare(!=) + + + ///Function gets part of WPathname + /** + @param path subject of examine + @param partnum zero-base index of part of WPathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count wchar_tacters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + static bool GetPartFromPath(const wchar_t *path, int partnum, wchar_t *buff, int bufsize, int mode=0); + + ///Function gets part of object + /** + @param partnum zero-base index of part of WPathname. Index 0 mostly contain drive or server, in case of + relative path, there is the name of the first folder or dots. + @param buff buffer for store result + @param bufsize count wchar_tacters in buffer; + @param mode mode=0, gets only name of part. + mode=1, get current part and remain parts of path. + mode=-1, gets all parts till current + @return Function returns true, if it was succesful, and it was not last part. Function returns + false, if it was succesful, and it was last part. Function returns false and sets buffer empty, + if an error occured. Function returns true and sets buffer empty, if buffer is too small to hold data + */ + bool GetPart(int partnum, wchar_t *buff, int bufsize,int mode=0) const + { + return GetPartFromPath(this->_fullpath,partnum,buff,bufsize,mode); + } + + /// Get Directory With Drive Without Last Back Slash + /** Retrieves into buffer directory with drive and removes last backslash + @param buff buffer that retrieves path + @param size size of buffer + @return true, if success, failed if buffer is too small*/ + + + bool GetDirectoryWithDriveWLBS(wchar_t *buff, size_t size) const; + + WString GetDirectoryWithDriveWLBS() const; + + + /// function checks, if path is valid and returns true, if does. + bool IsPathValid() const; + + /// Sets special directory. + /** + @param bSpecCode this value may be operation-system + depend. Windows implementation using CSIDL_XXXX constants, which is described in SHGetSpecialFolderLocation function + description + @return true, if function were successful + */ + bool SetDirectorySpecial(int nSpecCode); + + ///Sets temporaly directory. + bool SetTempDirectory(); + + ///Guess temporaly file name + /** + @param prefix prefix string for name + @param unique if unique is non-zero, it is used for new temporaly file. If unique is zero, function guess own unique + value. + @return true if function were successful + */ + bool SetTempFile(const wchar_t *prefix=L"tmp", unsigned int unique=NULL); + + ///Returns path of current executable. + /**It useful, when accessing folder, from when current module has been executed */ + static WPathname GetExePath(); + + ///Solves most used conversion from fullpath to path relative to project root + /** + @param full full WPathname with drive + @param projectRoot project root path + @return function returns pointer to full path, where starts relative part. If + fullpath doesn't contain project root path, it returns pointer to full. + @example FullToProjectRoot("x:\\project\\data\\example.txt","x:\\project"); //result is "data\\example.txt" + */ + + static const wchar_t *FullToRelativeProjectRoot(const wchar_t *full, const wchar_t *projectRoot); + + +protected: + ///Function only rebuild _fullpath string. + /** It doesn't check space for string! This function is used, when length of path is excepted + the same or smaller, then current. + */ + void RebuildPath(); + + +}; + + + +#endif // !defined(AFX_WPathname_H__158F59D5_B422_4FA6_86AC_10B5EC48C81B__INCLUDED_) diff --git a/DDLReader/WString.cpp b/DDLReader/WString.cpp new file mode 100644 index 0000000..1fa0cd6 --- /dev/null +++ b/DDLReader/WString.cpp @@ -0,0 +1,194 @@ +// WString.cpp: implementation of the WString class. +// +////////////////////////////////////////////////////////////////////// + +#include "WString.h" +#include +#include + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +WString::WString(const char *sbstring, unsigned int codePage) +{ + if (sbstring==NULL || *sbstring==0) + { + _ref=NULL; + } + else + { + size_t reqBuff=MultiByteToWideChar(codePage,0,sbstring,-1,NULL,0); + + _ref=WStringMemory::AllocString(NULL,reqBuff); + _ref->AddRef(); + wchar_t *str=const_cast(_ref->GetStringFromMemBlock()); + + MultiByteToWideChar(codePage,0,sbstring,-1,str,reqBuff); + } +} + +int WString::FormatV(wchar_t *format, va_list lst) +{ + size_t curSize=4096; + int written; + do + { + _ref=WStringMemory::AllocString(NULL,curSize); + wchar_t *str=const_cast(_ref->GetStringFromMemBlock()); + written=_vsnwprintf(str,curSize,format,lst); + if (written<0) + { + curSize*=2; + WStringMemory::FreeProxy(_ref); + } + } + while (written<-1); + _ref->RecalcLength(); + _ref->AddRef(); + return written; +} + +int WString::Format(wchar_t *format, ...) +{ + va_list valst; + va_start(valst,format); + return FormatV(format,valst); +} + + +int WString::ScanStringV(const wchar_t *format, va_list lst) const +{ + unsigned long *ptr=(unsigned long *)lst; + return swscanf(GetString(),format,ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5],ptr[6],ptr[7],ptr[8],ptr[9], + ptr[10],ptr[11],ptr[12],ptr[13],ptr[14],ptr[15],ptr[16],ptr[17],ptr[18],ptr[19]); + +} + +int WString::ScanString(const wchar_t *format, ...) const +{ + va_list valst; + va_start(valst,format); + return ScanStringV(format,valst); +} + +bool WString::ReplaceOnce(const WString &findWhat,const WString &replaceWith) +{ + int pos=Find(findWhat); + if (pos==-1) return false; + (*this)=Left(pos)+replaceWith+Right(pos+replaceWith.GetLength()); + return true; +} + +bool WString::ReplaceAll(const WString &findWhat,const WString &replaceWith) +{ + WString process=*this; + WString result; + int pos; + bool processed=false; + while ((pos=process.Find(findWhat))!=-1) + { + result=result+process.Left(pos)+replaceWith; + process=process.Right(pos+findWhat.GetLength()); + processed=true; + } + *this=result+process; + return processed; +} + +WString WString::TrimLeft() const +{ + return TrimLeft(L" \r\n\t"); +} + +WString WString::TrimRight() const +{ + return TrimRight(L" \r\n\t"); +} + +WString WString::TrimLeft(wchar_t *trimChars) const +{ + const wchar_t *proStr=GetString(); + int p=0; + while (proStr[p] && wcschr(trimChars,proStr[p]!=NULL)) p++; + return Right(p); +} + +WString WString::TrimRight(wchar_t *trimChars) const +{ + const wchar_t *proStr=GetString(); + int p=GetLength()-1; + while (p>=0 && wcschr(trimChars,proStr[p]!=NULL)) p--; + return Left(p+1); +} + +WString WString::Upper() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfUpper))); +} + +WString WString::Lower() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfLower))); +} + +WString WString::Reverse() const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,WStringProxy::EfReverse))); +} + +WString WString::Effect(IWStringEffect *effect) const +{ + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,effect))); +} + +void WString::SetUTF7(const char *utf7) +{ + *this=WString(utf7,CP_UTF7); +} + +void WString::SetUTF8(const char *utf8) +{ + *this=WString(utf8,CP_UTF8); +} + +const char *WString::AsSBString(unsigned int codePage, WString &holder) +{ + const wchar_t *str=GetString(); + if (str[0]==0) return ""; + size_t reqsize=WideCharToMultiByte(codePage,0,str,-1,NULL,0,NULL,NULL); + WStringProxy *holderProxy=WStringMemory::AllocString(NULL,reqsize/2); //reqsize/2+(2 bytes) + char *mbstr=reinterpret_cast(const_cast(holderProxy->GetStringFromMemBlock())); + WideCharToMultiByte(codePage,0,str,-1,mbstr,reqsize,NULL,NULL); + holder=WString(holderProxy); + return mbstr; +} + +const char *WString::AsUTF7(WString &holder) +{ + return AsSBString(CP_UTF7,holder); +} + +const char *WString::AsUTF8(WString &holder) +{ + return AsSBString(CP_UTF8,holder); +} + +void WString::ReadFromStream(size_t (*streamReader)(wchar_t *buffer, size_t bufferLen, void *context),void *context) +{ + _ref->Release(); + _ref=NULL; + wchar_t buff[256]; + size_t rd; + while ((rd=streamReader(buff,sizeof(buff)/sizeof(wchar_t),context))!=0) + { + *this=*this+WString(buff,rd); + } +} + +const WString WStringConst(const wchar_t *text) +{ + return WString(WStringMemory::AllocProxy(WStringProxy(text))); +} + diff --git a/DDLReader/WString.h b/DDLReader/WString.h new file mode 100644 index 0000000..a244adb --- /dev/null +++ b/DDLReader/WString.h @@ -0,0 +1,496 @@ +// WString.h: interface for the WString class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_) +#define AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WStringProxy.h" +#include + +class WString +{ + mutable WStringProxy *_ref; + + + +public: + ///constructs empty string + WString():_ref(0) {} + + ///constructs string. + explicit WString(const wchar_t *string):_ref(string==NULL?NULL:WStringMemory::AllocString(string,0)) {_ref->AddRef();}; + + ///constructs string from wide-char array with specified length + WString(const wchar_t *string, size_t sz):_ref(WStringMemory::AllocString(string,sz)) {_ref->AddRef();}; + + ///copy constructor + /**constructor doesn't copy the string, only reference. + String is shared until it is changed + */ + WString(const WString &other):_ref(other._ref) {_ref->AddRef();} + + ///constructs string from multi-byte string. codePage specified code page of string + WString(const char *sbstring, unsigned int codePage); + + ///constructs string from string-proxy. Used internally with WStringMemory::AllocXXX functions + WString(WStringProxy *proxy):_ref(proxy) {_ref->AddRef();} + + ///assignment operator + /** assignment operator doesn't copy the string only reference. + String is shared until it is changed */ + WString &operator=(const WString &other) + {other._ref->AddRef();_ref->Release();_ref=other._ref;return *this;} + + ///Destructor - releases reference + ~WString() {_ref->Release();} + + ///function converts instance of WString to wchar_t pointer + /** + Function will perform RenderString, if it is needed. + */ + const wchar_t *GetString() const + { + if (_ref==NULL) return L""; + WStringProxy *str=_ref->RenderString(); + if (_ref!=str) + { + str->AddRef();_ref->Release();_ref=str; + } + return _ref->GetStringFromMemBlock(); + } + + ///operator can convert WString to wchar_t pointer anytime + operator const wchar_t *() const {return GetString();} + + ///function returns count of characters in string + /** function doesn't need to render string, so it can be called anytime + without loosing the benefit of "pseudo-strings" boosting */ + size_t GetLength() const + { + if (_ref) return _ref->GetLength(); + else return 0; + } + + ///function creates string as sum of this and another string + /** function creates "pseudo-string" that represents sum of two string. + pseudo-string is rendered to "real-string" automatically, when it is needed */ + WString operator+(const WString other) const + { + if (_ref==NULL) return other; + if (other._ref==NULL) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,other._ref))); + } + + WString &operator+=(const WString other) + { + *this=*this+other; + return *this; + } + + ///function creates string as substring of another string + /** function creates "pseudo-string" that represents substring of anothers string. + Pseudo-string is rendered to "real-string" automatically, when it is needed */ + WString Mid(size_t begin, size_t len) const + { + if (begin==0) return Left(len); + if (_ref==NULL || begin>GetLength()) return WString(); + if (begin+len>GetLength()) return Right(begin); + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,begin,len))); + } + + WString Left(size_t len) const + { + if (_ref==NULL) return WString(); + if (len>=GetLength()) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,0,len))); + } + + WString Right(size_t begin) const + { + if (_ref==NULL || begin>GetLength()) return WString(); + if (begin==0) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,begin,GetLength()-begin))); + } + + WString RightR(size_t count) const + { + if (_ref==NULL || count==0) return WString(); + if (count>=GetLength()) return *this; + return WString(WStringMemory::AllocProxy(WStringProxy(_ref,GetLength()-count,count))); + } + + WString Delete(size_t begin, size_t count) const + { + if (_ref==NULL) return WString(); + if (begin==0) return Right(count); + if (begin+count>=GetLength()) return Left(begin); + return WString(WStringMemory::AllocProxy(WStringProxy(Left(begin)._ref,Right(begin+count)._ref))); + } + + WString Insert(const WString &what, size_t index) const + { + if (_ref==NULL) return what; + if (index==0) return what+*this; + if (index>=GetLength()) return *this+what; + return Left(index)+what+Right(index); + } + + /// function allows to access any char in string + wchar_t operator[](int index) const + { + assert(index<=(int)GetLength() && index>=0); + return GetString()[index]; + } + + /// functions allows lock string for accesing it directly. + /** Function returns pointer to buffer which holds string. + Buffer size is equal to string length plus terminating zero. + Application can modify content of buffer. + If string is shared with another WString object, LockBuffer + creates copy of string + Do not forger to call UnlockBuffer, when you finish modifiing the content + */ + wchar_t *LockBuffer() + { + if (_ref==NULL) return NULL; + GetString(); + WStringMemory::LockProxy(_ref); + if (_ref->IsShared()) + { + WStringMemory::UnlockProxy(_ref); + _ref->Release(); + _ref=WStringMemory::AllocString(_ref->GetStringFromMemBlock(),0); + _ref->AddRef(); + WStringMemory::LockProxy(_ref); + } + return const_cast(_ref->GetStringFromMemBlock()); + } + + /// Function creates buffer for string and returns its address + /** Application can use buffer in functions, that cannot work with + WString objects. Size of buffer is specified by sz value, and it is in characters. + Application must call UnlockBuffer after writes all data into buffer. + + NOTE: Prevoius content of string is lost. + NOTE: sz specifies buffer size without terminating zero character + */ + wchar_t *CreateBuffer(size_t sz) + { + _ref->Release(); + _ref=WStringMemory::AllocString(NULL,sz); + _ref->AddRef(); + WStringMemory::LockProxy(_ref); + return const_cast(_ref->GetStringFromMemBlock()); + } + + /// Function creates buffer, and copies string into it. + /** Parameter sz specifies size of new buffer in characters + When sz is smaller then size of string, string is truncated + When sz is larger then size of string, string is copied unchanged, + but extra characters can be appended. + + NOTE: sz specifies buffer size without terminating zero character + */ + wchar_t *CreateBufferCopy(size_t sz) + { + WString save=*this; + wchar_t *wbuff=CreateBuffer(sz); + int minsz=__min(sz,save.GetLength()); + wcsncpy(wbuff,save.GetString(),minsz); + return wbuff; + } + + /// Function unlocks internal buffer + /** parameter sz specifies final lenght of string in buffer. Default + value -1 forces function calc size by own + */ + void UnlockBuffer(int sz=-1) + { + if (_ref==NULL) return; + wchar_t *wbuff=const_cast(_ref->GetStringFromMemBlock()); + if (sz<0) sz=wcslen(wbuff); + else wbuff[sz]=0; + if (sz!=(signed)_ref->GetLength()) + { + _ref->RecalcLength(); + WStringMemory::UnlockProxy(_ref); + } + } + + class WStringAtCharHelper + { + WString &_str; + size_t _index; + public: + WStringAtCharHelper(WString &str,size_t index):_str(str),_index(index) {} + WString &operator=(wchar_t z) + { + wchar_t *buff=_str.LockBuffer(); + assert(buff && _index<_str.GetLength()); + buff[_index]=z; + _str.UnlockBuffer(); + return _str; + } + operator wchar_t() + { + assert(_index<_str.GetLength()); + return ((const wchar_t *)_str)[_index]; + } + }; + + /// Function will return helper object, which can access single character in string + /** + Using array operator is slower than accessing characters by LockBuffer function + */ + WStringAtCharHelper operator[](int index) + { + return WStringAtCharHelper(*this,index); + } + + int Find(wchar_t z,size_t from=0) const + { + if (from>=GetLength()) return -1; + const wchar_t *res=wcschr(GetString()+from,z); + if (res) return res-GetString(); + else return -1; + } + + int FindLast(wchar_t z) const + { + const wchar_t *res=wcsrchr(GetString(),z); + if (res) return res-GetString(); + else return -1; + } + + int Find(const wchar_t *z,size_t from=0) const + { + if (z==NULL) return -1; + if (from>=GetLength()) return -1; + const wchar_t *res=wcsstr(GetString()+from,z); + if (res) return res-GetString(); + else return -1; + } + + int FormatV(wchar_t *format, va_list lst); + + int Format(wchar_t *format, ...); + + ///Scans string for format + /** function is limited, item count is limited up to 20 items */ + int ScanStringV(const wchar_t *format, va_list lst) const; + + ///Scans string for format + /** function is limited, item count is limited up to 20 items */ + int ScanString(const wchar_t *format, ...) const; + + bool ReplaceOnce(const WString &findWhat,const WString &replaceWith); + + bool ReplaceAll(const WString &findWhat,const WString &replaceWith); + + WString TrimLeft() const; + + WString TrimRight() const; + + WString TrimLeft(wchar_t *trimChars) const; + + WString TrimRight(wchar_t *trimChars) const; + + ///Function splits string into two + /** Left part of string is returned. + Right part of string is leaved in object + @param splitPos split position. + @return if splitPos==0, function returns empty string. if splitPos>=length, function + moves string from object to result*/ + WString Split(size_t splitPos) + { + WString result=Left(splitPos); + *this=Right(splitPos); + return result; + } + + bool IsEmpty() const {return _ref==NULL;} + + void Empty() const {_ref->Release();_ref=NULL;} + + int Compare(const wchar_t *other) const + { + return wcscmp(*this,other); + } + + bool operator>(const WString &other) const {return Compare(other)>0;} + bool operator<(const WString &other) const {return Compare(other)<0;} + bool operator>=(const WString &other) const {return Compare(other)>=0;} + bool operator<=(const WString &other) const {return Compare(other)<=0;} + bool operator!=(const WString &other) const {return Compare(other)<=0;} + bool operator==(const WString &other) const {return Compare(other)<=0;} + + WString Upper() const; + WString Lower() const; + WString Reverse() const; + + ///Applies user effect on string + /** pointer should be static allocated object, or must be valid during lifetime of resulting string */ + WString Effect(IWStringEffect *effect) const; + + void SetUTF7(const char *utf7); + void SetUTF8(const char *utf8); + + ///Function converts string to SingleByte string + /** + @param codePage Platform depends code page of result + @param holder Object that holds result. Result pointer is valid during lifetime of holder. Once holder + released, pointer is invalidated. You can get resulting pointer anytime from holder reintepreting + wchar_t to char + @result pointer to string + */ + const char *AsSBString(unsigned int codePage, WString &holder); + + ///Returns multibyte string in UTF7 codepage + /**See AsSBString description*/ + const char *AsUTF7(WString &holder); + + ///Returns multibyte string in UTF7 codepage + /**See AsSBString description*/ + const char *AsUTF8(WString &holder); + + + ///Function reads string from stream + /** + Function calls streamReader repeatly until function returns zero. In each call, streamReader returns + number of characters, that has been readed. + @param sreamReader pointer to function which provides reading from a stream + @param context user defined context pointer (most in cases, pointer to stream is passed) + @param buffer space allocated for data readed from stream + @param bufferLen maximum count of characters can be written to buffer + @return streamReader returns number of characters, that has been written to buffer. Function must return zero + to stop reading + */ + void ReadFromStream(size_t (*streamReader)(wchar_t *buffer, size_t bufferLen, void *context),void *context); + + WString operator() (int from) const {return from<0?RightR(-from):Right(from);} + WString operator() (int from, int to) const + { + if (from>=0) + return to<0?Mid(from,-to):Mid(from,to-from); + else + return to<0?Mid(GetLength()+from,-to):Mid(GetLength()+from,GetLength()-from-to); + } + + ///Enables global string sharing. + /** Function Share allows share strings that contains same text. It can reduce memory + usage. Function is useful when there is many objects that contains string with same text. + + Basically, two strings is shared, if one string is created as copy of another string. Strings + is sharing they content, until one of them is modified. + + Calling Share function, string is registered for global sharing. If string with same content is already + registered, then content of current string is released, and string is shared. + + To successfully share two strings, both strings must call Share() function. Sharing is provided until one + of strings is modified. After modifications are done, Share function of modified string must be called again. + + Remember: Global sharing can reduce amount of memory, if there are multiple strings that containging + the same content. But sharing of each unique string takes small piece of memory to store sharing + informations. + + To share string automatically, use WSharedString class + WSC strings cannot be shared! + */ + void Share() const + { + WStringProxy *curref=_ref; + GetString(); + _ref=WStringMemory::ShareString(curref); + _ref->AddRef(); + curref->Release(); + } + + ///Disables global string sharing + /** Function unregisters string from global sharing database. If string is shared, function doesn't break + it. But all strings that currently sharing content will not be shared with newly created strings. + */ + void Unshare() + { + WStringMemory::UnshareString(_ref); + } +}; + +///Function will create constant WString +/** function will not copy content of string. Only creates reference to string + Using WStringConst is faster for strings in code +@exmple result=a+WStringConst(L"text")+b; +*/ +const WString WStringConst(const wchar_t *text); + +///Macro to easy convert incode string to WString +/** +function also marks text wide. +@example WString text=WSC("Hello world"); +*/ +#define WSC(x) WStringConst(L##x) +///Macro to easy convert any wchar_t buffer to constant WString +/** +IMPORTANT NOTE!: Buffer must exists until string is rendered. +If you are using WSCB in function, don't forget call GetString before function exits +If you are excepting additional string operations outside function, using standard +WString conversion can be more effecient. +*/ +#define WSCB(x) WStringConst(x) + + + +class WSharedString: public WString +{ +public: + WSharedString() {} + + ///constructs string. + explicit WSharedString(const wchar_t *string):WString(string) {Share();} + + ///constructs string from wide-char array with specified length + WSharedString(const wchar_t *string, size_t sz):WString(string,sz) {Share();}; + + ///copy constructor + /**constructor doesn't copy the string, only reference. + String is shared until it is changed + */ + WSharedString(const WSharedString &other):WString(other) {} + WSharedString(const WString &other):WString(other) {Share();} + + ///constructs string from multi-byte string. codePage specified code page of string + WSharedString(const char *sbstring, unsigned int codePage):WString(sbstring,codePage) {Share();} + + ///assignment operator + /** assignment operator doesn't copy the string only reference. + String is shared until it is changed */ + WSharedString &operator=(const WString &other) + {WString::operator =(other);Share();return *this;} + + const wchar_t *GetString() const + { + const wchar_t *res=WString::GetString(); + Share(); + return res; + } + operator const wchar_t *() const {return GetString();} + wchar_t operator[](int index) const + { + assert(index<=(int)GetLength() && index>=0); + return GetString()[index]; + } + + void UnlockBuffer(int sz=-1) + { + WString::UnlockBuffer(sz); + Share(); + } + +}; + + +#endif // !defined(AFX_WSTRING_H__481164FB_3BB7_4824_B0E3_8B371F0AAF3A__INCLUDED_) diff --git a/DDLReader/WStringMemory.cpp b/DDLReader/WStringMemory.cpp new file mode 100644 index 0000000..947ed02 --- /dev/null +++ b/DDLReader/WStringMemory.cpp @@ -0,0 +1,397 @@ +// WStringMemorySingleThread.cpp: implementation of the WStringMemory class. +// +////////////////////////////////////////////////////////////////////// + +#include +#include +#include "WStringMemory.h" +#include "WStringProxy.h" +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +#ifdef _MT //multithreading +#define WSTRING_MT +#endif + +#ifdef WSTRING_MT //multithreading + + +struct WStringMTLock +{ + WStringProxy *_lockProxy; + LONG _recursionCount; + DWORD _owner; + HANDLE _event; + WStringMTLock(WStringProxy *x):_lockProxy(x) {} + WStringMTLock():_lockProxy(NULL) {} + + bool operator==(const WStringMTLock &other) const {return _lockProxy==other._lockProxy;} + bool operator!=(const WStringMTLock &other) const {return _lockProxy!=other._lockProxy;} + bool operator>=(const WStringMTLock &other) const {return _lockProxy>=other._lockProxy;} + bool operator<=(const WStringMTLock &other) const {return _lockProxy<=other._lockProxy;} + bool operator>(const WStringMTLock &other) const {return _lockProxy>other._lockProxy;} + bool operator<(const WStringMTLock &other) const {return _lockProxy *GLockDB=NULL; //Lock proxy database + +static void exitMT() +{ + DeleteCriticalSection(&GLocker); +} + + +static void OnStartup() +{ + InitializeCriticalSection(&GLocker); + atexit(exitMT); +} + +#define ON_STARTUP_PRIORITY_NORMAL OnStartup +#include + +#endif + + + +#define WS_MAXFREELISTS 32 +#define WS_FREELISTSTEP 32 +#define WS_TOTALMAXFREEKBYTES 256 + +#define WS_MAXIMUMFASTALLOC (WS_MAXFREELISTS*WS_FREELISTSTEP) + +#define WS_MAXFREEBYTES PerSlotMaxAlloc + + +static size_t PerSlotMaxAlloc=(WS_TOTALMAXFREEKBYTES*1024/WS_MAXFREELISTS); +static WStringProxy *FreeList=NULL; +static void **StringFreeList[WS_MAXFREELISTS]; +static size_t StringFreeBytes[WS_MAXFREELISTS]; +static bool InitManager=true; + + +static void InitManagerPointers() +{ + memset(StringFreeList,0,sizeof(StringFreeList)); + memset(StringFreeBytes,0,sizeof(StringFreeBytes)); + InitManager=false; +} + +static void *AllocStringBlock(size_t sz) +{ + if (InitManager) InitManagerPointers(); + if (sz>WS_MAXIMUMFASTALLOC) return malloc(sz); + int pos=(sz+WS_FREELISTSTEP-1)/WS_FREELISTSTEP; + void **nxt=StringFreeList[pos]; + if (nxt==0) + { + printf("malloc %d\n",pos*WS_FREELISTSTEP); + return malloc(pos*WS_FREELISTSTEP); + } + printf("fast_alloc %d\n",pos*WS_FREELISTSTEP); + StringFreeList[pos]=(void **)(*nxt); + StringFreeBytes[pos]-=_msize(nxt); + return nxt; +} + +static void DeallocStringBlock(void *ptr) +{ + size_t sz=_msize(ptr); + if (sz>WS_MAXIMUMFASTALLOC) {free(ptr);return;} + int pos=(sz+WS_FREELISTSTEP-1)/WS_FREELISTSTEP; + if (sz+StringFreeBytes[pos]>WS_MAXFREEBYTES) + { + printf("free %d\n",sz); + free(ptr);return; + } + void **proxy=(void **)ptr; + *proxy=(void *)StringFreeList[pos]; + StringFreeList[pos]=proxy; + StringFreeBytes[pos]+=sz; + printf("fast_free %d\n",sz); +} + + +static inline void *operator new(size_t alloc,size_t sz) +{ + return AllocStringBlock(sz+alloc); +} + +static inline void operator delete(void *p,size_t alloc) +{ + DeallocStringBlock(p); +} + +static inline void *operator new(size_t sz,void *ptr) +{ + return ptr; +} + +static inline void operator delete(void *ptr,void *p) +{ +} + +WStringProxy * WStringMemory::AllocString(const wchar_t *text, size_t size) +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + assert(size!=0 || text!=0); + if (size==0) size=wcslen(text); + WStringProxy *proxy=new((size+1)*sizeof(wchar_t)) WStringProxy(size,0,0); + wchar_t *alloctext=const_cast(proxy->GetStringFromMemBlock()); + if (text) wcsncpy(alloctext,text,size); + alloctext[size]=0; + if (proxy->_redirect==0) + { + proxy->_redirect=alloctext; + proxy->_blockData2=1; + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return proxy; +} + +WStringProxy * WStringMemory::AllocProxy(const WStringProxy &templateProxy) +{ + WStringProxy * res; +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + if (FreeList==NULL) res=new WStringProxy(templateProxy); + else + { + WStringProxy *alloc=FreeList; + FreeList=alloc->_baseString; + res=new((void *)alloc) WStringProxy(templateProxy); + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return res; +} + +void WStringMemory::FreeProxy(WStringProxy *proxy) +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + if (proxy->_operation==proxy->OpMemBlck && !(proxy->_blockData2==0 && proxy->_redirect!=NULL)) + { + if (proxy->_blockData2==2) UnshareString(proxy); + DeallocStringBlock(proxy); + } + else + { + proxy->~WStringProxy(); + proxy->_baseString=FreeList; + FreeList=proxy; + } +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif +} + +#ifdef WSTRING_MT + +void WStringMemory::LockProxy( WStringProxy *proxy) +{ +nextTry: + EnterCriticalSection(&GLocker); + WStringMTLock srch(proxy),*found; + if (GLockDB==NULL) GLockDB=new BTree(16); + found=GLockDB->Find(srch); + if (found==NULL) + { + srch._event=NULL; + srch._owner=GetCurrentThreadId(); + srch._recursionCount=1; + GLockDB->Add(srch); + } + else + { + if (found->_owner!=GetCurrentThreadId()) + { + HANDLE w=found->_event; + if (w==0) {w=found->_event=CreateEvent(NULL,TRUE,FALSE,NULL);} + LeaveCriticalSection(&GLocker); //leave section + WaitForSingleObject(w,INFINITE); + goto nextTry; + } + else + { + found->_recursionCount++; + } + } + LeaveCriticalSection(&GLocker); //leave section +} + +void WStringMemory::UnlockProxy( WStringProxy *proxy) +{ + EnterCriticalSection(&GLocker); + WStringMTLock srch(proxy),*found; + found=GLockDB->Find(srch); + if (found) + { + if (--found->_recursionCount==0) + { + if (found->_event!=NULL) + { + SetEvent(found->_event); + CloseHandle(found->_event); + } + GLockDB->Remove(*found); + } + } + LeaveCriticalSection(&GLocker); +} + + +void WStringMemory::AddRefProxy(WStringProxy *proxy) +{ + InterlockedIncrement(reinterpret_cast(&proxy->_refCount)); +} + +bool WStringMemory::ReleaseRefProxy(WStringProxy *proxy) +{ + LONG res=InterlockedDecrement(reinterpret_cast(&proxy->_refCount)); + if (res<0) res=InterlockedIncrement(reinterpret_cast(&proxy->_refCount)); + return res==0; +} + +#else +void WStringMemory::LockProxy( WStringProxy *proxy) +{ + //not needed in single thread environment +} + +void WStringMemory::UnlockProxy( WStringProxy *proxy) +{ + //not needed in single thread environment +} + + +void WStringMemory::AddRefProxy(WStringProxy *proxy) +{ + //no special handling in single thread environment + ++proxy->_refCount; +} + +bool WStringMemory::ReleaseRefProxy(WStringProxy *proxy) +{ + //no special handling in single thread environment + if (proxy->_refCount) --proxy->_refCount; + return proxy->_refCount==0; +} + +#endif +void WStringMemory::FreeExtra() +{ +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + while (FreeList) + { + void *proxy=FreeList; + FreeList=FreeList->_baseString; + free(proxy); + } + for (int i=0;i_redirect,other._str->_redirect); + } + + bool operator==(const ShareDBItem& other) const {return Compare(other)==0;} + bool operator>=(const ShareDBItem& other) const {return Compare(other)>=0;} + bool operator<=(const ShareDBItem& other) const {return Compare(other)<=0;} + bool operator!=(const ShareDBItem& other) const {return Compare(other)!=0;} + bool operator>(const ShareDBItem& other) const {return Compare(other)>0;} + bool operator<(const ShareDBItem& other) const {return Compare(other)<0;} +}; + +static BTree *GDB=NULL; + +WStringProxy *WStringMemory::ShareString(WStringProxy *proxy) +{ + if (proxy->_operation!=WStringProxy::OpMemBlck || proxy->_blockData2==0 || proxy->_blockData2==2) return proxy; + +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + + if (GDB==NULL) GDB=new BTree; + + proxy->_blockData2=2; //block is subject of sharing + proxy->_redirect=proxy->GetStringFromMemBlock(); //setup pointer to string + ShareDBItem *found=GDB->Find(ShareDBItem(proxy)); + if (found) {proxy->_blockData2=1;proxy=found->_str;} + else GDB->Add(ShareDBItem(proxy)); +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif + return proxy; +} + +void WStringMemory::UnshareString(WStringProxy *proxy) +{ + if (proxy->_operation!=WStringProxy::OpMemBlck || proxy->_blockData2!=2) return; + if (GDB==NULL) return; +#ifdef WSTRING_MT + EnterCriticalSection(&GLocker); +#endif + GDB->Remove(ShareDBItem(proxy)); + proxy->_blockData2=1; +#ifdef WSTRING_MT + LeaveCriticalSection(&GLocker); +#endif +} \ No newline at end of file diff --git a/DDLReader/WStringMemory.h b/DDLReader/WStringMemory.h new file mode 100644 index 0000000..a81b08e --- /dev/null +++ b/DDLReader/WStringMemory.h @@ -0,0 +1,61 @@ +// WStringMemory.h: interface for the WStringMemory class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_) +#define AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_ + +#include + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class WStringProxy; + +class WStringMemory +{ +public: + + static WStringProxy * AllocString(const wchar_t *text, size_t size); + static WStringProxy * AllocProxy(const WStringProxy &templateProxy); + static void FreeProxy(WStringProxy *proxy); + static void LockProxy(WStringProxy *proxy); + static void UnlockProxy(WStringProxy *proxy); + + //Releases extra memory leaved for future fast allocations + static void FreeExtra(); + + //Support addref for proxy - Single- or Multi- thread support + static void AddRefProxy(WStringProxy *proxy); + + //Support addref for proxy - Single- or Multi- thread support + //returns true, when counter reached zero + static bool ReleaseRefProxy(WStringProxy *proxy); + + ///Gets statistics about memory manager + /** + @param details optional pointer to 32 size_t items. Array will be filled + with sizes of each string fastalloc group. + @return function returns total bytes allocated for string fast allocation. + (This number should be below 256KB) + */ + static size_t GetStatistics(size_t *details=NULL); + + ///Function allows sharing the strings + /** This function is called by WString::Share function + Function mark proxy shared. If string is same as shared, + it returns pointer to proxy with proxy of string that contains + the same text. + Read description of WString::Share for more informations + */ + static WStringProxy *ShareString(WStringProxy *proxy); + + ///Function disables sharing of the string + static void UnshareString(WStringProxy *proxy); + +}; + + + +#endif // !defined(AFX_WSTRINGMEMORY_H__79693029_4788_4099_9A97_92AF310A7AD5__INCLUDED_) diff --git a/DDLReader/WStringProxy.cpp b/DDLReader/WStringProxy.cpp new file mode 100644 index 0000000..6b93900 --- /dev/null +++ b/DDLReader/WStringProxy.cpp @@ -0,0 +1,185 @@ +// WStringProxy.cpp: implementation of the WStringProxy class. +// +////////////////////////////////////////////////////////////////////// + + +#include "WStringProxy.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +/** Funkce vytvoří transitivní uzávěr. +to znamená, že zruší všechny zřetězené redirecty. +*/ +WStringProxy *WStringProxy::TransitivniUzaver() +{ + if (_operation==OpSubstr && _offset==0 && _stringSize==_baseString->GetLength()) + { + WStringProxy *next=_baseString->TransitivniUzaver(); + if (next==NULL) return this; + next->AddRef(); + _baseString->Release(); + _baseString=next; + return next; + } + return NULL; +} + +/** Main render procedure +It creates allocates buffer proxy and renders tree into it +Then turns self into redirect proxy a redirect self into newly created string +Rerurns pointer to newly created proxy +*/ +WStringProxy *WStringProxy::RenderString() +{ + if (_operation==OpMemBlck) return this; + + WStringProxy *pp=TransitivniUzaver(); + if (pp!=NULL) return pp->_baseString->RenderString(); + + WStringProxy *newProxy=WStringMemory::AllocString(NULL,_stringSize); + wchar_t *renderPtr=const_cast(newProxy->GetStringFromMemBlock()); + + RenderStringToBuffer(renderPtr); + + newProxy->AddRef(); + this->~WStringProxy(); + _operation=OpSubstr; + _offset=0; + _baseString=newProxy; + + return newProxy; +} + +/** Function renders simple effect into buffer +Function needs buffer with nul terminated string +*/ +void WStringProxy::RenderSimpleEffect(wchar_t *renderPtr) +{ + assert(_operation==OpEffect); + switch (_effect) + { + case EfLower: wcslwr(renderPtr);break; + case EfUpper: wcsupr(renderPtr);break; + case EfReverse: wcsrev(renderPtr);break; + } + +} + +/** Light phase of rendering. Used to render string that is not +created from substring. This part is optimized for concat and user effects +When substring must be rendered, function call RenderStringToBufferSubstr to +render substring. +*/ +void WStringProxy::RenderStringToBuffer(wchar_t *renderPtr) +{ + WStringMemory::LockProxy(this); + switch (_operation) + { + case OpConcat: + _baseString->RenderStringToBuffer(renderPtr); + _secondString->RenderStringToBuffer(renderPtr+_baseString->GetLength()); + break; + case OpSubstr: + { + _baseString->RenderStringToBufferSubstr(renderPtr,_offset,GetLength()); + } + break; + case OpMemBlck: + { + const wchar_t *str=GetStringFromMemBlock(); + wcsncpy(renderPtr,str,_stringSize); + } + break; + case OpEffect: + { + unsigned long offset=0; + renderPtr[_stringSize]=0; //we can append zero, because right side of string is not yet rendered + //if this is end of string, one extra character for zero is also allocated. + //efect functions can rely on it. + if (_blockData2>=256) offset=_userEffect->PreRenderString(renderPtr,_baseString->GetLength()); //call prerender to prepare begin of buffer + _baseString->RenderStringToBuffer(renderPtr+offset); //render string to rest of buffer + if (_blockData2>=256) _userEffect->RenderString(renderPtr,_baseString->GetLength()); //apply effect to buffer + else RenderSimpleEffect(renderPtr); + } + break; + }; + WStringMemory::UnlockProxy(this); +} + +/** +Deep phase of rendering. Function can render substrings, or render substring of two +concated strings. Function can also perform partial effect on string. Function cannot +handle partial user effect, so this effects are converted to things strings. +*/ +void WStringProxy::RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size) +{ + WStringMemory::LockProxy(this); + switch (_operation) + { + case OpConcat: + { + //process substring of concat + //count characters in buffer + size_t rendered; + //when string starts in left string + if (_baseString->GetLength()>offset) + { + //calculate total characters that may be rendered + rendered=_baseString->GetLength()-offset; + //but limit it to request size + if (rendered>size) rendered=size; + //render substring into buffer + _baseString->RenderStringToBufferSubstr(renderPtr,offset,rendered); + } + else + //no character has been rendered + rendered=0; + + //there is still characters remained to render. We will take it from second string + if (size-rendered>0) + { + if (offset>_baseString->GetLength()) offset-=_baseString->GetLength(); + else offset=0; + _secondString->RenderStringToBufferSubstr(renderPtr+rendered,offset,size-rendered); + } + } + break; + case OpSubstr: + { //rendering substrings is very easy + offset+=_offset; //add offset of substring + assert(offset+size<=GetLength()); //check length + //render substring + this->RenderStringToBufferSubstr(renderPtr,offset,size); + } + break; + case OpMemBlck: + { + //rendering from memory, final stop in recursion + //Get pointer string + const wchar_t *str=GetStringFromMemBlock(); + //copy substring from string into render buffer + wcsncpy(renderPtr,str+offset,size); + } + break; + case OpEffect: + if (_blockData2>=256) //interface cannot handle partial rendering + { + RenderString(); //convert proxy to simple redirect and render it + RenderStringToBufferSubstr(renderPtr,offset,size); //now we are able to cut out part + } + else + { + //all standard effects maps string 1:1 + //first get content of substring into buffer + _baseString->RenderStringToBufferSubstr(renderPtr,offset,size); + //we can append zero, because right side of string is not yet rendered + renderPtr[size]=0; + //process effect on target + RenderSimpleEffect(renderPtr); + } + break; + }; + WStringMemory::UnlockProxy(this); +} \ No newline at end of file diff --git a/DDLReader/WStringProxy.h b/DDLReader/WStringProxy.h new file mode 100644 index 0000000..e5f470b --- /dev/null +++ b/DDLReader/WStringProxy.h @@ -0,0 +1,232 @@ +// WStringProxy.h: interface for the WStringProxy class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) +#define AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "WStringMemory.h" +#include "IWStringEffect.h" +#include +#include +#include +#include + +/* +List of proxy types + +Memory_Proxy _operation=OpMemBlck + _blockData==0 and _blockData2==0 + or + _blockData!=0 and _blockData2!=0 + (_redirect - debug pointer) + (_blockData - 1) + +Proxy_Const _operation=OpMemBlck + _redirect - pointer to string + _blockData2=0 + +Proxy_Shared _operation=OpMemBlck + _redirect - pointer to string + _blockData2=2; + +Proxy_Immediate _operation=OpMemBlck + _blockData>0xFFFF + _blockData2>0xFFFF + both parameters are used by immediate memory manager + +Proxy_Concat _operation=OpConcat + _baseString and _secondString is valid + +Proxy_Link _operation=OpSubstr + _baseString is valid + _stringSize==_baseString->_stringSize + _offset==0; + NOTE: Can be used without rendering + +Proxy_RightSub _operation=OpSubstr + _baseString is valid + _offset<=_baseString->_stringSize + _stringSize==_baseString->_stringSize-_offset + NOTE: Can be used without rendering + +Proxy_SubString _operation=OpSubstr + _baseString is valid + _offset<=_baseString->_stringSize + _stringSize<=_baseString->_stringSize-_offset + +Proxy_Effect _operation=OpEffect + _baseString is valid + _stringSize=_baseString->_stringSize + _effect defining effect code < 0xFFFF + +Proxy_UserEffect _operation=OpEffect + _baseString is valid + _stringSize=_baseString->_stringSize + _effect>0xFFFF + _userEffect defining pointer to effect interface + +*/ +class WStringProxy +{ +public: + enum Operation + { + OpConcat=0, //proxy contains two links to concat it + OpSubstr=1, //proxy contains link to another proxy and specified substring + OpMemBlck=-2, //proxy contains informations about following string + OpEffect=-1, //proxy describing some efect with string + }; + + enum Effect + { + EfLower, //effect lower case + EfUpper, //effect upper case + EfReverse, //effect reverse string + }; +public: + + unsigned long _refCount; //reference count + unsigned long _stringSize:30; //string size in characters (maximum size 1073741823 characters ~ 2147483646 bytes) + Operation _operation:2; //operation with string or proxy type + + union + { + WStringProxy *_baseString; //pointer to next proxy referenced by this proxy + unsigned long _blockData; //user defined block data for OpMemBlock proxy type + const wchar_t *_redirect; //used for OpMemBlock, when _blockData2 is zero. + }; + + union + { + WStringProxy *_secondString; //pointer to second string for OpConcat + unsigned long _offset; //offset of substring for OpSubstr + Effect _effect; //effect selector for OpEffect + IWStringEffect *_userEffect; //user effect defined by IWStringEffect interface (valid when _effect is invalid) + unsigned long _blockData2; //user defined block data for OpMemBlock proxy type - exception: if this value is zero, member _redirect is valid + + }; + + + void RenderStringToBuffer(wchar_t *renderPtr); + void RenderStringToBufferSubstr(wchar_t *renderPtr, size_t offset, size_t size); + WStringProxy *TransitivniUzaver(); + void RenderSimpleEffect(wchar_t *renderPtr); + +public: + WStringProxy():_refCount(0),_operation(OpSubstr),_stringSize(0),_baseString(0),_secondString(0) {} //inicializes empty string proxy + + WStringProxy(WStringProxy *other): + _refCount(0), + _stringSize(other->GetLength()), + _baseString(other), + _operation(OpSubstr), + _offset(0) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *other, unsigned long offset, unsigned long size): + _refCount(0), + _stringSize(size), + _baseString(other), + _operation(OpSubstr), + _offset(offset) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *a, WStringProxy *b): + _refCount(0), + _stringSize(a->GetLength()+b->GetLength()), + _baseString(a), + _operation(OpConcat), + _secondString(b) + {_baseString->AddRef();_secondString->AddRef();} + + WStringProxy(WStringProxy *a, Effect effect): + _refCount(0), + _stringSize(a->GetLength()), + _baseString(a), + _operation(OpEffect), + _effect(effect) + {_baseString->AddRef();} + + WStringProxy(WStringProxy *a, IWStringEffect *userEffect): + _refCount(0), + _stringSize(a->GetLength()+userEffect->GetEffectExtraSize(a->GetLength())), + _baseString(a), + _operation(OpEffect), + _userEffect(userEffect) + {_baseString->AddRef();} + + WStringProxy(unsigned long size, unsigned long user1, unsigned long user2): + _refCount(0), + _stringSize(size), + _operation(OpMemBlck), + _blockData(user1), + _blockData2(user2) + {} + + WStringProxy(const wchar_t *imText): + _refCount(0), + _stringSize(wcslen(imText)), + _redirect(imText), + _blockData2(0), + _operation(OpMemBlck) + {} + + WStringProxy(const WStringProxy &other) + { + memcpy(this,&other,sizeof(*this)); + if (_operation!=OpMemBlck) _baseString->AddRef(); + if (_operation==OpConcat) _secondString->AddRef(); + } + + WStringProxy& operator=(const WStringProxy &other) + { + WStringProxy::~WStringProxy(); //call destructor to destruct current proxy + memcpy(this,&other,sizeof(*this)); //construct new proxy from template + if (_operation!=OpMemBlck) _baseString->AddRef(); + if (_operation==OpConcat) _secondString->AddRef(); + } + + WStringProxy *RenderString(); + + ~WStringProxy() + { + if (_operation!=OpMemBlck) _baseString->Release(); + if (_operation==OpConcat) _secondString->Release(); + } + + + unsigned long GetLength() {return _stringSize;} + void AddRef() {if (this) WStringMemory::AddRefProxy(this);} + void Release() {if (this) if (WStringMemory::ReleaseRefProxy(this)) WStringMemory::FreeProxy(this);} + + const wchar_t *GetString() + { + if (_operation==OpMemBlck) return (const wchar_t *)(this+1); + WStringProxy *p=RenderString(); + (*this)=*p; + return (const wchar_t *)(p+1); + } + + const wchar_t *GetStringFromMemBlock() + { + assert(_operation==OpMemBlck); + if (_blockData2==0 && _redirect!=NULL) return _redirect; + else return (const wchar_t *)(this+1); + } + + bool IsShared() {return _refCount>1;} + + void RecalcLength() + { + const wchar_t *str=GetStringFromMemBlock(); + _stringSize=wcslen(str); + } + +}; + +#endif // !defined(AFX_WSTRINGPROXY_H__863ADE82_7789_4E54_BE7D_B8F0740FD81B__INCLUDED_) diff --git a/DDLReader/res/DDLReader.ico b/DDLReader/res/DDLReader.ico new file mode 100644 index 0000000..7eef0bc Binary files /dev/null and b/DDLReader/res/DDLReader.ico differ diff --git a/DDLReader/res/DDLReader.rc2 b/DDLReader/res/DDLReader.rc2 new file mode 100644 index 0000000..35693f0 --- /dev/null +++ b/DDLReader/res/DDLReader.rc2 @@ -0,0 +1,13 @@ +// +// DDLREADER.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/DDLReader/resource.h b/DDLReader/resource.h new file mode 100644 index 0000000..2625141 --- /dev/null +++ b/DDLReader/resource.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by DDLReader.rc +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_DDLREADER_DIALOG 102 +#define IDS_FILEOPENFAILED 102 +#define IDC_HEADGROUP 103 +#define IDC_HEADFNAME 104 +#define IDC_HEADSIZE 105 +#define IDC_HEADOFFSET 106 +#define IDS_DDLFILTER 107 +#define IDC_GROUP_GRAPHICS 108 +#define IDC_GROUP_SOUNDS 109 +#define IDC_GROUP_FONTS 110 +#define IDC_GROUP_BASIC 111 +#define IDC_GROUP_ITEMS 112 +#define IDC_GROUP_MONSTERS 113 +#define IDC_GROUP_DIALOGS 114 +#define IDC_GROUP_UNSPECIFIED 115 +#define IDC_GROUP_UNKNOWN 116 +#define IDS_UNABLETOCREATEFILE 117 +#define IDS_UNABLETOEXTACTDATA 118 +#define IDR_MAINFRAME 128 +#define IDD_PROGRESS 129 +#define IDD_EXPORTING 129 +#define IDC_FILELIST 1001 +#define IDC_FOLDER 1002 +#define IDC_BROWSE 1003 +#define IDC_EXPORT 1004 +#define IDC_POPISEK 1005 +#define IDC_DDLFILE 1006 +#define IDC_DDLBROWSE 1007 +#define IDC_PROGRESS 1008 +#define IDC_NAME 1009 +#define IDC_BUTTON1 1010 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1011 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/FONT/BIG.FON b/FONT/BIG.FON new file mode 100644 index 0000000..8034176 Binary files /dev/null and b/FONT/BIG.FON differ diff --git a/FONT/BIG2.FON b/FONT/BIG2.FON new file mode 100644 index 0000000..65524ae Binary files /dev/null and b/FONT/BIG2.FON differ diff --git a/FONT/BOLDCZ.FON b/FONT/BOLDCZ.FON new file mode 100644 index 0000000..be5e16c Binary files /dev/null and b/FONT/BOLDCZ.FON differ diff --git a/FONT/BROOKLIN.FON b/FONT/BROOKLIN.FON new file mode 100644 index 0000000..733c5e5 Binary files /dev/null and b/FONT/BROOKLIN.FON differ diff --git a/FONT/EUROMODE.FON b/FONT/EUROMODE.FON new file mode 100644 index 0000000..398e4db Binary files /dev/null and b/FONT/EUROMODE.FON differ diff --git a/FONT/FONT4X8.FON b/FONT/FONT4X8.FON new file mode 100644 index 0000000..f918236 Binary files /dev/null and b/FONT/FONT4X8.FON differ diff --git a/FONT/FONT5X8.FON b/FONT/FONT5X8.FON new file mode 100644 index 0000000..d39b3e2 Binary files /dev/null and b/FONT/FONT5X8.FON differ diff --git a/FONT/FONT6X9.FON b/FONT/FONT6X9.FON new file mode 100644 index 0000000..ddc1006 Binary files /dev/null and b/FONT/FONT6X9.FON differ diff --git a/FONT/IKONES.FON b/FONT/IKONES.FON new file mode 100644 index 0000000..36a9495 Binary files /dev/null and b/FONT/IKONES.FON differ diff --git a/FONT/KNIHA.FON b/FONT/KNIHA.FON new file mode 100644 index 0000000..371eba4 Binary files /dev/null and b/FONT/KNIHA.FON differ diff --git a/FONT/SADA16.FON b/FONT/SADA16.FON new file mode 100644 index 0000000..4ff2637 Binary files /dev/null and b/FONT/SADA16.FON differ diff --git a/FONT/SADA7.FON b/FONT/SADA7.FON new file mode 100644 index 0000000..f548b55 Binary files /dev/null and b/FONT/SADA7.FON differ diff --git a/FONT/TIMESBIG.FON b/FONT/TIMESBIG.FON new file mode 100644 index 0000000..0b1a6bd Binary files /dev/null and b/FONT/TIMESBIG.FON differ diff --git a/FONT/TIMESBIT.FON b/FONT/TIMESBIT.FON new file mode 100644 index 0000000..4d7f635 Binary files /dev/null and b/FONT/TIMESBIT.FON differ diff --git a/FONT/TIMESE.FON b/FONT/TIMESE.FON new file mode 100644 index 0000000..460b558 Binary files /dev/null and b/FONT/TIMESE.FON differ diff --git a/FONT/TINY.FON b/FONT/TINY.FON new file mode 100644 index 0000000..371eba4 Binary files /dev/null and b/FONT/TINY.FON differ diff --git a/FONT/ikony.fon b/FONT/ikony.fon new file mode 100644 index 0000000..12f8f96 Binary files /dev/null and b/FONT/ikony.fon differ diff --git a/GAME/AUTOMAP.C b/GAME/AUTOMAP.C new file mode 100644 index 0000000..04b2bb0 --- /dev/null +++ b/GAME/AUTOMAP.C @@ -0,0 +1,954 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" + +#define AUTOMAP_BACK RGB555(8,4,0) +#define AUTOMAP_VODA RGB555(0,15,31) +#define AUTOMAP_LAVA RGB555(31,16,0) +#define AUTOMAP_FORE RGB555(18,17,14) +#define AUTOMAP_LINE1 RGB555(13,11,10) +#define AUTOMAP_LINE2 RGB555(31,22,6) +#define AUTOMAP_MOB RGB555(31,8,8) + +#define MEDIUM_MAP 9 +#define MEDIUM_MMAP 4 +#define MEDIUM_MAP_COLOR RGB555(21,20,19) +#define MEDIUM_MAP_LINE1 RGB555(25,20,17) +#define MEDIUM_MAP_LINE2 RGB555(31,22,6) + +word stairs_colors[]= + {AUTOMAP_LINE1, + RGB555(14,12,11), + RGB555(15,14,12), + RGB555(16,15,12), + RGB555(17,16,13)}; + +word arrow_colors[]= + { + AUTOMAP_LINE1, + AUTOMAP_FORE + }; + +char shift_map(int id,int xa,int ya,int xr,int yr); +char psani_poznamek(int id,int xa,int ya,int xr,int yr); +char map_target_select(int id,int xa,int ya,int xr,int yr); +char map_target_cancel(int id,int xa,int ya,int xr,int yr); +char map_menu(int id,int xa,int ya,int xr,int yr); +char map_menu_glob_map(int id,int xa,int ya,int xr,int yr); + +char noarrows=0; +char enable_glmap=0; + +static int map_xr,map_yr; +static int cur_depth; +TSTR_LIST texty_v_mape=NULL; + +#define BOTT 378 +#define LEFT 520 + +static char cur_disables; + +#define CLK_MAP_VIEW 5 +T_CLK_MAP clk_map_view[]= + { + {MS_GAME_WIN,0,17,639,377,psani_poznamek,2,H_MS_DEFAULT}, + {-1,54,378,497,474,start_invetory,2+8,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,LEFT,BOTT,639,479,map_menu,2,H_MS_DEFAULT}, + {-1,0,0,639,479,return_game,8,-1}, + }; + +#define CLK_GLOB_MAP 4 +T_CLK_MAP clk_glob_map[]= + { + {-1,54,378,497,474,start_invetory,2+8,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,LEFT,BOTT,639,479,map_menu,2,H_MS_DEFAULT}, + {-1,0,0,639,479,map_menu_glob_map,8,-1}, + }; + +#define CLK_TELEPORT_VIEW 4 +T_CLK_MAP clk_teleport_view[]= + { + {MS_GAME_WIN,0,17,639,377,map_target_select,2,H_MS_DEFAULT}, + {-1,LEFT,BOTT,639,479,map_target_cancel,2,H_MS_DEFAULT}, + {-1,0,0,639,479,map_target_cancel,8,-1}, + {-1,0,0,639,479,empty_clk,0xff,-1}, + }; + + +char testclip(int x,int y) + { + return (y>=16 && y<360+16 && x>=8 && x<630); + } + +/*void shift_map_event(EVENT_MSG *msg,int *data) + { + static int smer; + + data; + if (msg->msg==E_INIT) smer=*(int *)msg->data; + else if (msg->msg==E_TIMER) + { + switch (smer) + { + case H_SIPKY_S:send_message(E_KEYBOARD,'H'*256);break; + case H_SIPKY_J:send_message(E_KEYBOARD,'P'*256);break; + case H_SIPKY_V:send_message(E_KEYBOARD,'M'*256);break; + case H_SIPKY_Z:send_message(E_KEYBOARD,'K'*256);break; + case H_SIPKY_SZ:send_message(E_KEYBOARD,'s'*256);msg->msg=-2;break; + case H_SIPKY_SV:send_message(E_KEYBOARD,'t'*256);msg->msg=-2;break; + } + } + else if (msg->msg==E_MOUSE) + { + MS_EVENT *ms; + + ms=get_mouse(msg); + if (!ms->tl1 && !ms->tl2) + { + send_message(E_DONE,E_TIMER,shift_map_event); + msg->msg=-2; + schovej_mysku(); + other_draw(); + ukaz_mysku(); + showview(0,0,0,0); + } + } + } + */ + +void save_text_to_map(int x,int y,int depth,char *text) + { + char c[512],*d; + if (text[0]==0) return; + memset(c,1,sizeof(c)); + strcpy(c+12,text); + if (texty_v_mape==NULL) texty_v_mape=create_list(8); + d=texty_v_mape[str_add(&texty_v_mape,c)]; + x=(x-320)+map_xr; + y=(y-197)+map_yr; + memcpy(d,&x,4);memcpy(d+4,&y,4);memcpy(d+8,&depth,4); + } + +static char check_for_layer(int layer) + { + int i; + TMAP_EDIT_INFO *m=map_coord; + + for(i=0;ilayer==layer && m->flags & MC_MARKED && m->flags & MC_AUTOMAP) return 1; + return 0; + } + +void ukaz_vsechny_texty_v_mape() + { + int x,y,d,i,cn; + char *c; + + if (texty_v_mape==NULL) return; + set_font(H_FLITT5,NOSHADOW(0)); + cn=str_count(texty_v_mape); + for(i=0;i640) + { + *d=e; + d--;e=*d;*d=0; if (d==c) break; + } + position(x,y);outtext(c); + *d=e; + } + else if(x<8 && x+text_width(c)>10 && y>16 && y<376) + { + char cd[2]=" "; + while (x<10 && *c) + { + cd[0]=*c++;x+=text_width(cd); + } + position(x,y);outtext(c); + } + } + } + } + +void psani_poznamek_event(EVENT_MSG *msg,void **data) + { + static int x,y; + static char text[255],index; + static char *save; + static void *save_pic=NULL; + + data; + if (msg->msg==E_INIT) + { + int *p; + char *c; + + set_font(H_FLITT5,NOSHADOW(0)); + p=msg->data; + x=p[0]; + y=p[1]; + c=*(char **)(p+2); + strcpy(text,c); + save=(char *)getmem(strlen(text)+1); + strcpy(save,text); + index=strchr(text,0)-text; + if (save_pic==NULL) + { + schovej_mysku(); + save_pic=getmem(640*20*2+6); + get_picture(0,y,640,20,save_pic); + position(x,y);outtext(text);outtext("_"); + showview(0,0,640,480); + } + } + else + if (msg->msg==E_MOUSE) + { + MS_EVENT *ms; + + ms=get_mouse(msg); + if (ms->event_type & 0x8) send_message(E_KEYBOARD,27); + msg->msg=-1; + } + else if (msg->msg==E_KEYBOARD) + { + char c; + + c=*(char *)msg->data; + set_font(H_FLITT5,NOSHADOW(0)); + if (c) + { + switch (c) + { + case 8:if (index) index--; text[index]=0;break; + case 27:strcpy(text,save); + case 13:save_text_to_map(x,y,cur_depth,text); + send_message(E_DONE,E_MOUSE,psani_poznamek_event);msg->msg=-2;return; + default:if (c>=32) + { + text[index]=c; + text[index+1]=0; + if (text_width(text)>(640-x)) text[index]=0; else index++; + } + } + put_picture(0,y,save_pic); + position(x,y);outtext(text);outtext("_"); + showview(x,y,640,20); + } + msg->msg=-1; + } + else if (msg->msg==E_DONE) + { + if (save_pic!=NULL) + { + put_picture(0,y,save_pic); + showview(x,y,640,y+20); + free(save_pic);save_pic=NULL; + send_message(E_AUTOMAP_REDRAW); + ukaz_mysku(); + } + if (save!=NULL) + { + free(save);save=NULL; + } + } + } + +int hledej_poznamku(int x,int y,int depth) + { + int i,count; + + x=(x-320)+map_xr; + y=(y-197)+map_yr; + if (texty_v_mape==NULL) return -1; + count=str_count(texty_v_mape); + set_font(H_FLITT5,NOSHADOW(0)); + for(i=0;i=xa && y>=ya && x<=xb && y<=yb && dep==depth) + { + xas=(xa+320)-map_xr; + yas=(ya+197)-map_yr; + xbs=xas+xs; + ybs=yas+ys; + if (xas>0 && xbs<640 && yas>16 && ybs<360+16) return i; + return -2; + } + } + return -1; + } + +char psani_poznamek(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr; + + if (noarrows) return 1; + if ((id=hledej_poznamku(xa,ya,cur_depth))==-1) + { + xa&=~7;xa+=2; + ya&=~7;ya-=4; + send_message(E_ADD,E_KEYBOARD,psani_poznamek_event,xa,ya,""); + send_message(E_ADD,E_MOUSE,psani_poznamek_event,xa,ya,""); + } + else if (id!=-2) + { + char *s; + + xa=*(int *)(texty_v_mape[id]); + ya=*(int *)(texty_v_mape[id]+4); + xa=(xa+320)-map_xr; + ya=(ya+197)-map_yr; + s=(char *)getmem(strlen(texty_v_mape[id]+12)+1); + strcpy(s,texty_v_mape[id]+12); + str_remove(&texty_v_mape,id); + str_delfreelines(&texty_v_mape); + send_message(E_AUTOMAP_REDRAW); + for(xr=0;xr<10;xr++) do_events(); + send_message(E_ADD,E_KEYBOARD,psani_poznamek_event,xa,ya,s); + send_message(E_ADD,E_MOUSE,psani_poznamek_event,xa,ya,s); + free(s); + } + return 0; + } + +char shift_map(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + + anim_sipky(id,1); +// send_message(E_ADD,E_TIMER,shift_map_event,id); +// send_message(E_ADD,E_MOUSE,shift_map_event,id); + return 0; + } + +static void print_symbol(int x,int y,char znak) + { + char c[2]=" "; + position(x+1,y+1);c[0]=znak;outtext(c); + } + + +static void draw_amap_sector(int x,int y,int sector,int mode,int turn,int line1,int line2) + { + int j,i,k; + TSTENA *q; + TSECTOR *ss; + + q=&map_sides[sector<<2]; + ss=&map_sectors[sector]; + if (ss->sector_type==S_VODA || ss->sector_type==S_LODKA) curcolor=AUTOMAP_VODA; + else if (ss->sector_type==S_LAVA) curcolor=AUTOMAP_LAVA; + else curcolor=AUTOMAP_FORE; + if (!mode) + { + trans_bar(x,y,8,8,curcolor); + if ((k=map_coord[sector].flags & 0x600)!=0) + { + int i; + + i=map_sectors[sector].sector_type; + set_font(H_FSYMB,0);k>>=9; + switch (k) + { + case 3:break; + case 2:set_font(H_FSYMB,0); + font_color(stairs_colors); + print_symbol(x,y,'s');break; + case 1:set_font(H_FSYMB,0); + font_color(arrow_colors); + print_symbol(x,y,4+((i-S_SMER+4-turn) & 0x3));break; + + } + } + else + switch(map_sectors[sector].sector_type) + { + int i; + TSTENA *sd; + case S_SCHODY:set_font(H_FSYMB,0x3e0); + memcpy(charcolors,stairs_colors,sizeof(stairs_colors)); + print_symbol(x,y,'s');break; + case S_TELEPORT:for(i=0,sd=map_sides+sector*4;i<4 && ~sd->flags & SD_SEC_VIS;i++,sd++); + if (i!=4) {set_font(H_FSYMB,0x3e0);print_symbol(x,y,'T');}break; + case S_DIRA:set_font(H_FSYMB,NOSHADOW(0));print_symbol(x,y,'N');break; + } + } + else + for(j=0;j<4;j++) + { + i=(j+turn)&3; + if (!(q[i].flags & SD_TRANSPARENT)||(q[i].flags & SD_SECRET)) curcolor=line1; + else if (q[i].flags & SD_PLAY_IMPS) curcolor=line2; + else curcolor=AUTOMAP_FORE; + if (q[i].flags & SD_INVIS) curcolor=AUTOMAP_FORE; + if (curcolor!=AUTOMAP_FORE) + { + switch (j) + { + case 0:hor_line(x,y,x+8);break; + case 1:ver_line(x+8,y,y+8);break; + case 2:hor_line(x,y+8,x+8);break; + case 3:ver_line(x,y,y+8);break; + } + } + } + + } + +void herni_cas(char *s) + { + int mes,den,hod,min; + long cas; + + cas=game_time; + mes=cas/(360*24*30);cas%=360*24*30; + den=cas/(360*24);cas%=360*24; + hod=cas/(360);cas%=360; + min=cas/6; + + if (mes) + { + sprintf(s,texty[cislovka(mes)+149],mes); + strcat(s," "); + s=strchr(s,0); + } + if (den) + { + sprintf(s,texty[cislovka(den)+146],den); + strcat(s," "); + s=strchr(s,0); + } + sprintf(s,texty[152],hod,min); + } + +static void zobraz_herni_cas(void) + { + static char text[100]; + static long old_time=-1; + char cas[100]; + + if (old_time!=game_time) + { + herni_cas(cas); + strcpy(text,texty[145]); + strcat(text," "); + strcat(text,cas); + old_time=game_time; + } + set_font(H_FONT6,NOSHADOW(0)); + set_aligned_position(635,372,2,2,text); + outtext(text); + } + + +extern word color_butt_on[]; +extern word color_butt_off[]; + +static void displ_button(char disable,char **text) + { + int posy[]={0,18,37,55}; + int sizy[]={18,20,20,21}; + int i; + + cur_disables=disable; + set_font(H_FTINY,0); + put_picture(LEFT,BOTT,ablock(H_CHARGEN)); + for(i=0;i<4;i++) + { + if (disable & 1) + { + put_8bit_clipped(ablock(H_CHARGENB),(392+posy[i])*scr_linelen2+524+GetScreenAdr(),posy[i],96,sizy[i]); + font_color(color_butt_off); + } + else + { + font_color(color_butt_on); + } + disable>>=1; + set_aligned_position(LEFT+50,BOTT+14+13+i*19,1,2,*text); + outtext(*text); + text++; + } + } + + +void draw_automap(int xr,int yr) +{ + int i,k,x,y,xp,yp; + int depth; + TSTENA *q; + word *s; + + update_mysky(); + schovej_mysku(); + put_textured_bar(ablock(H_BACKMAP),0,17,640,360,-xr*8,-yr*8); + curcolor=AUTOMAP_BACK; + xp=map_coord[viewsector].x*8; + yp=map_coord[viewsector].y*8; + depth=cur_depth; + map_xr=xp-xr*8; + map_yr=yp-yr*8; + for(k=0;k<2;k++) + for(i=1;i=-178 && y<170 && x>=-312 && x<310) + { + + x+=320;y+=197; + draw_amap_sector(x,y,i,k,0,AUTOMAP_LINE1,AUTOMAP_LINE2); + if (map_coord[i].flags & MC_PLAYER && !noarrows) + { + int j,l=-1; + + for(j=0;jmsg==E_INIT) xr=yr=0; + if (msg->msg==E_IDLE && draw==1) + { + draw_automap(xr,yr); + draw=0; + } + else draw--; + if (msg->msg==E_AUTOMAP_REDRAW) draw=4; + if (msg->msg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + switch (c) + { + case 'H':yr++;draw=4;break; + case 'P':yr--;draw=4;break; + case 'M':xr--;draw=4;break; + case 'K':xr++;draw=4;break; + case 'Q': + case 's':if (check_for_layer(cur_depth-1)) cur_depth--;draw=4;break; + case 'I': + case 't':if (check_for_layer(cur_depth+1)) cur_depth++;draw=4;break; + case 15: + case 50: + case 1: + (*(int *)msg->data)=0; + unwire_proc(); + wire_proc(); + + break; + } + } + return &map_keyboard; + } + +void show_automap(char full) + { + mute_all_tracks(0); + unwire_proc(); + if (full) enable_all_map(); + hold_timer(TM_FAST_TIMER,1); + unwire_proc=unwire_automap; + schovej_mysku(); + if (cur_mode!=MD_ANOTHER_MAP) bott_draw(1),cur_mode=MD_MAP; + other_draw(); + if (!battle && full && enable_glmap) displ_button(cur_mode==MD_ANOTHER_MAP?4:6,texty+210); + else displ_button(7,texty+210); + ukaz_mysku(); + showview(0,376,640,480); + cur_depth=map_coord[viewsector].layer; + draw_automap(0,0); + send_message(E_ADD,E_KEYBOARD,map_keyboard); + send_message(E_ADD,E_AUTOMAP_REDRAW,map_keyboard); + send_message(E_ADD,E_IDLE,map_keyboard); + change_click_map(clk_map_view,CLK_MAP_VIEW); +} + +static char mob_not_invis(sector) + { + int m; + m=mob_map[sector]; + while (m) + { + m--;if (mobs[m].vlastnosti[VLS_KOUZLA] & SPL_INVIS) return 0; + m=mobs[m].next; + } + return 1; + } + +void draw_medium_map() + { + int xr, yr; + int xp, yp; + int xc,yc,x,y; + int j,i,k,layer; + //char c=" "; + + xp=MEDIUM_MMAP*8+5; + yp=MEDIUM_MMAP*8+20; + layer=map_coord[viewsector].layer; + xr=map_coord[viewsector].x; + yr=map_coord[viewsector].y; + trans_bar(0,17,MEDIUM_MAP*8+6*2,MEDIUM_MAP*8+4*2,0); + for(j=0;j<2;j++) + for(i=1;i=-MEDIUM_MMAP && yc>=-MEDIUM_MMAP && yc<=MEDIUM_MMAP && xc<=MEDIUM_MMAP) + { + draw_amap_sector(x=xc*8+xp,y=yc*8+yp,i,j,viewdir &3,MEDIUM_MAP_LINE1,MEDIUM_MAP_LINE2); + if (j) + if (mob_map[i] && mob_not_invis(i) && battle) + { + position(x+1,y+1);set_font(H_FSYMB,AUTOMAP_MOB); + outtext("N"); + } + if (map_coord[i].flags & MC_PLAYER) + { + int u=-1,z=-1; + for(k=0;k4) return 1; + id--; + if (cur_disables & (1<xa) cur_page=xa; + if (cur_page!=oldp) play_sample_at_channel(H_SND_KNIHA,1,100); + wire_kniha(); + return 1; + } + +#define CLK_KNIHA 3 +T_CLK_MAP clk_kniha[]= + { + {2,320,0,639,479,page_change,2,-1}, + {-2,0,0,319,479,page_change,2,-1}, + {-1,0,0,639,479,exit_kniha,8,-1}, + }; + + +void unwire_kniha() +{ + hold_timer(TM_FAST_TIMER,0); + GlobEvent(MAGLOB_AFTERBOOK,viewsector,viewdir); +} + + +void wire_kniha() + { + int xa; + if (!GlobEvent(MAGLOB_BEFOREBOOK,viewsector,viewdir)) + { + return; + } + xa=count_pages(); + xa=((xa-1) & ~1)+1; + if (cur_page<1) cur_page=1; + if (cur_page>xa) cur_page=xa; + mute_all_tracks(0); + unwire_proc(); + schovej_mysku(); + put_picture(0,0,ablock(H_KNIHA)); + change_click_map(clk_kniha,CLK_KNIHA); + unwire_proc=unwire_kniha; + set_font(H_FONT6,NOSHADOW(0)); + write_book(cur_page); + ukaz_mysku(); + showview(0,0,0,0); + hold_timer(TM_FAST_TIMER,1); + } + +static last_selected; + +char map_target_cancel(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + return exit_wait=1; + } + +void map_teleport_keyboard(EVENT_MSG *msg,void **usr) + { + usr; + if (msg->msg==E_KEYBOARD) + switch (*(short *)msg->data>>8) + { + case 1: + case 15: + case 50: exit_wait=1; msg->msg=-1;break; + } + } + + +static char path_ok(word sector) + { + map_coord[sector].flags|=MC_MARKED; + return 1; + } + +char map_target_select(int id,int xa,int ya,int xr,int yr) + { + int x1,y1,x2,y2; + + ya,xa; + for (id=1;id=x1 && xr<=x2 && yr>=y1 && yr<=y2) + { + if (!labyrinth_find_path(viewsector,id,SD_PLAY_IMPS,path_ok,NULL)) return 0; + last_selected=id; + exit_wait=1; + return 1; + } + } + return 0; + } + + +int select_teleport_target() + { + *otevri_zavoru=1; + unwire_proc(); + disable_all_map(); + labyrinth_find_path(viewsector,65535,SD_PLAY_IMPS,path_ok,NULL); + map_coord[viewsector].flags|=MC_MARKED; + schovej_mysku(); + send_message(E_ADD,E_KEYBOARD,map_teleport_keyboard); + show_automap(0); + change_click_map(clk_teleport_view,CLK_TELEPORT_VIEW); + last_selected=0; + ukaz_mysku(); + escape(); + send_message(E_DONE,E_KEYBOARD,map_teleport_keyboard); + disable_all_map(); + return last_selected; + } diff --git a/GAME/BOLDCZ.FON b/GAME/BOLDCZ.FON new file mode 100644 index 0000000..be5e16c Binary files /dev/null and b/GAME/BOLDCZ.FON differ diff --git a/GAME/BUILDER.C b/GAME/BUILDER.C new file mode 100644 index 0000000..514327a --- /dev/null +++ b/GAME/BUILDER.C @@ -0,0 +1,1315 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include "Version.h" + +#define ZIVOTY_S 60 +#define ZIVOTY_E 62 +#define KONDIC_S 64 +#define KONDIC_E 66 +#define MANA_S 68 +#define MANA_E 70 +#define BARS_S 13 +#define BARS_E 85 +#define BARS_YS (BARS_E-BARS_S) +#define PIC_X 3 +#define PIC_Y 12 +#define MANA_COLOR RGB555(15,0,31) +#define SEL_COLOR RGB555(31,31,31) + +#define ZASAHB_X 8 +#define ZASAHB_Y 20 +#define ZASAHT_X 30 +#define ZASAHT_Y 38 + + +#define SHOW {swap_buffs();showview(0,0,0,0);swap_buffs();getche();`} + +#define HUMAN_ADJUST 97 + +unsigned short barvy_skupin[POCET_POSTAV+1]= + { + RGB555(8,8,8), + RGB555(31,28,00), + RGB555(00,23,06), + RGB555(31,11,13), + RGB555(22,16,31), + RGB555(28,13,31), + RGB555(00,29,26) + }; + +char reverse_draw=0; +int viewsector=1,viewdir=1; +char norefresh=0,cancel_render=0,map_state=0; +int cur_sector; //sektor aktualni pozice +int back_color; +char global_anim_counter=0; +char one_buffer=0; +char set_halucination=0; +int hal_sector; +int hal_dir; +char see_monster=0; +char lodka=0; +int bgr_distance=0; //vzdalenost pozadi od pohledu +int bgr_handle=0; + +int spell_handle=0,spell_phase,spell_xicht; + +THE_TIMER *bott_timer=NULL; +char *bott_text=NULL; +char bott_display; +char true_seeing=0; +char obl_anim_counter=0; +char obl_max_anim=1; +char anim_mirror=0; +static char showrune=0; +static int showruneitem=0; + + + +char dirs[10]; +word minimap[VIEW3D_Z+1][VIEW3D_X*2+1]; + + + +//debug - !!!! + +int dhit=0; +int ddef=0; +int ddostal=0; +int dlives=0; +int dmzhit=0; +int dsee=0; +char show_debug=0; +char *debug_text; +char marker=0; + + +SPECTXT_ARR spectxtr; +static char spt_ptr=0; + + +void add_spectxtr(word sector,word fhandle,word count,word repeat,integer xpos) + { + SPECTXTR *sp=spectxtr+spt_ptr; + + sp->sector=sector; + sp->handle=fhandle; + sp->count=count; + sp->pos=0; + sp->repeat=repeat; + sp->xpos=xpos; + if (count) + if ((++spt_ptr)>=MAX_SPECTXTRS) spt_ptr=0; + map_coord[sector].flags |= MC_SPECTXTR; + } + +void calc_spectxtrs(void) + { + int i; + + for(i=0;ipos>=sp->count) + { + sp->pos=0;if (sp->repeat>0) sp->repeat--; + } + } + } + +static void draw_spectxtrs(word sector,int celx,int cely) + { + int i; + char a=1; + + if (!(map_coord[sector].flags & MC_SPECTXTR)) return; + for(i=0;ihandle+sp->pos),celx,cely,sp->xpos); + a=0; + } + if (a) + map_coord[sector].flags &= ~MC_SPECTXTR; + } + +void init_spectxtrs(void) + { + memset(spectxtr,0,sizeof(spectxtr)); + } + +void ukaz_kompas(char mode) + { + static int phase=0,speed=0; + int direct; + + if (mode==1) + { + direct=(3-viewdir); + direct=phase-direct*10; + if (direct<-20) direct+=40; + if (direct>=20) direct-=40; + speed=((direct>0)-(direct<0)); + } + if (mode!=255) put_image(ablock(H_KOMPAS),GetScreenAdr()+476,phase*16,102,16); + if (mode==1) + { + phase-=speed;if (phase>39) phase=0; + if(phase<0) phase=39; + } + if (mode==255) showview(476,0,102,15); + } + +void show_money() + { + char c[20]; + set_font(H_FONT7,RGB555(28,28,21)); + sprintf(c,"%d",money); + set_aligned_position(460,13,2,2,c); + outtext(c); + } + + +void anim_sipky(int h,int mode) + { + static int phase=0; + static char drw=0; + static short handle=0; + + if (mode==1) + { + handle=h; + phase=6; + return; + } + if (phase && mode!=255) + { + int i; + + if (phase>4) i=8-phase; else i=phase; + i=(i-2)*110; + if (i>=0) + put_8bit_clipped(ablock(handle),GetScreenAdr()+378*scr_linelen2+498,i,142,102); + else put_picture(498,378,ablock(H_SIPKY_END)); + drw=1; + if (mode!=-1) + { + phase--; + } + } + if (mode==255 && drw) + { + showview(498,378,142,102); + drw=0; + } + } + +void chveni(int i) + { + static int pos=0; + static int count=0; + + if (!count && !i) return; + if (i) count=i;count--; + if (!count) pos=0; + wait_retrace(); + setvesa_displaystart(8*pos,0); + pos=!pos; + } + +void objekty_mimo() + { + schovej_mysku(); + ukaz_kompas(1); + anim_sipky(0,0); + ukaz_mysku(); + ukaz_kompas(255); + anim_sipky(0,255); + chveni(0); + } + +void draw_blood(char mode,int mob_dostal,int mob_dostal_pocet) + { + static int phase=100; + static int block; + static int dostal; + char s[20]; + word *adr; + int i; + + mob_dostal_pocet; + if (mode) { + if (phase<3) dostal+=mob_dostal_pocet;else dostal=mob_dostal_pocet; + phase=0; + block=mob_dostal; + return; + } + if (phase>7) return; + adr=520+378*scr_linelen2+GetScreenAdr(); + i=105*phase; + phase++; + put_8bit_clipped(ablock(H_KREVMIN+block-1),adr,i,120,102); + set_font(H_FTINY,RGB555(31,31,31)); + itoa(dostal,s,10); + set_aligned_position(60+520,51+378,1,1,s);outtext(s); + } + +word *bott_clear(void) + { + word *bott_scr; + + bott_scr=(word *)getmem(scr_linelen2*104*2); + memset(bott_scr,0,_msize(bott_scr)); + return bott_scr; + } + +static void draw_small_icone(int num,int x,int y) + { + word *pic; + + pic=ablock(H_POSTUP); + num*=13;x+=num; + put_textured_bar(pic,x,y,13,13,num,0); + } + +static void bott_fletna_normal(void **pp,long *s) + { + word *bott_scr; + int i,x; + bott_scr=bott_clear(); + RedirectScreen(bott_scr); + put_picture(0,0,ablock(H_FLETNA_BAR)); + set_font(H_FTINY,RGB555(31,31,0)); + set_aligned_position(103,52,1,1,texty[174]);outtext(texty[174]); + for(i=0,x=156;i<12;i++,x+=22) + { + set_aligned_position(x,32,1,1,texty[180+i]);outtext(texty[180+i]); + } + *pp=GetScreenAdr(); + *s=_msize(*pp); + RestoreScreen(); + } + +static void bott_draw_normal(void **pp,long *s) + { + int i,j;int x,xs=0,y; + word *bott_scr; + THUMAN *p; + + bott_scr=bott_clear(); + RedirectScreen(bott_scr); + if (battle && cur_mode==MD_INBATTLE) put_picture(0,0,ablock(H_BATTLE_BAR)); + else put_picture(0,0,ablock(H_DESK)); + memcpy(&xs,ablock(H_OKNO),2); + x=54; + for(j=0;jused) + if (cur_mode!=MD_PRESUN || i==moving_player) + { + char c[]=" ";int z,lv,llv; + put_picture(x,0,ablock(H_OKNO));lv=p->lives;llv=p->vlastnosti[VLS_MAXHIT]; + if (lv || p->used & 0x80) + { + z=3-((lv-1)*4/llv);if (lv==llv) z=0; + z*=75; + if (p->xicht>=0)put_8bit_clipped(ablock(H_XICHTY+i),bott_scr+PIC_X+x+PIC_Y*scr_linelen2,z,54,75); + if (p->bonus) draw_small_icone(0,PIC_X+x+1,PIC_Y+1); + if (p->spell) draw_small_icone(1,PIC_X+x+1,PIC_Y+1); + if (!p->voda) draw_small_icone(2,PIC_X+x+1,PIC_Y+1); + if (!p->jidlo) draw_small_icone(3,PIC_X+x+1,PIC_Y+1); + } + else put_picture(PIC_X+x,PIC_Y,ablock(H_LEBKA)); + curcolor=0; + y=BARS_YS-p->lives*BARS_YS/p->vlastnosti[VLS_MAXHIT]; + if (y) bar(x+ZIVOTY_S,BARS_S,x+ZIVOTY_E,BARS_S+y); + y=BARS_YS-p->kondice*BARS_YS/p->vlastnosti[VLS_KONDIC]; + if (y) bar(x+KONDIC_S,BARS_S,x+KONDIC_E,BARS_S+y); + if (p->vlastnosti[VLS_MAXMANA]) y=BARS_YS-p->mana*BARS_YS/p->vlastnosti[VLS_MAXMANA];else y=BARS_YS; + if (y<0) y=0; + if (y) bar(x+MANA_S,BARS_S,x+MANA_E,BARS_S+y); + if (p->sektor!=viewsector) trans_bar25(x,0,74,102); + set_font(H_FLITT,p->groupnum==cur_group && !battle?SEL_COLOR:barvy_skupin[p->groupnum]); + set_aligned_position(x+36,92,1,0,p->jmeno);outtext(p->jmeno); + c[0]=p->groupnum+48;set_aligned_position(x+5,86,0,2,c);outtext(c); + if (cur_mode==MD_INBATTLE) + { + char s[20]; + signed char dir; + set_font(H_FBOLD,RGB555(31,31,0)); + sprintf(s,texty[40],p->actions); + set_aligned_position(x+56,86,2,2,s);outtext(s); + dir=viewdir-p->direction; + if (abs(dir)==2) c[0]=2; + else if (dir==-1 || dir==3) c[0]=1; + else if (dir==-3 || dir==1) c[0]=3; + if (dir) + { + set_font(H_FSYMB,p->groupnum==cur_group && !battle?SEL_COLOR:barvy_skupin[p->groupnum]); + c[0]+=4;set_aligned_position(x+10,86,0,2,c);outtext(c); + } + } + if (i==select_player) rectangle(x+3,12,x+3+54,12+75,SEL_COLOR); + if (p->dostal) + { + char s[20]; + put_picture(x+ZASAHB_X,ZASAHB_Y,ablock(H_PZASAH)); + set_font(H_FBOLD,RGB555(31,31,0)); + sprintf(s,"%d",p->dostal); + set_aligned_position(x+ZASAHT_X,ZASAHT_Y,1,1,s);outtext(s); + } + x+=xs; + } + if (cur_mode==MD_PRESUN || cur_mode==MD_UTEK) + { + char s[40]; + set_font(H_FBOLD,RGB555(31,31,16)); + position(150,20);outtext(texty[cur_mode==MD_PRESUN?42:44]); + sprintf(s,texty[60+cislovka(postavy[moving_player].actions)],postavy[moving_player].actions); + position(150,35);outtext(s); + position(150,50);outtext(texty[63]); + } +/* if (mob_dostal) + { + word *w; + char s[40]; + + w=ablock(H_MZASAH1+mob_dostal-1); + put_picture(580-(w[0]>>1),55-(w[1]>>1),w); + itoa(mob_dostal_pocet,s,10); + set_font(H_FLITT5,0xffff); + set_aligned_position(580,55,1,1,s); + outtext(s); + } + */ + *pp=GetScreenAdr(); + *s=_msize(*pp); + RestoreScreen(); + } + + +void bott_timer_draw(struct the_timer *q) + { + q; + bott_display=BOTT_NORMAL; + zneplatnit_block(H_BOTTBAR); + free(bott_text); + bott_text=NULL; + bott_timer=NULL; + } + +void bott_disp_text_proc(void **pp,long *ss) + { + char *p,*text; + int y=20; + int xx,yy; + + text=alloca(strlen(bott_text)+2); + set_font(H_FBOLD,NOSHADOW(0)); + zalamovani(bott_text,text,390,&xx,&yy); + RedirectScreen(bott_clear()); + if (battle && cur_mode==MD_INBATTLE) put_picture(0,0,ablock(H_BATTLE_BAR)); + else put_picture(0,0,ablock(H_DESK)); + create_frame(70,20,400,50,1); + p=text; + do + { + position(70,y); + outtext(p); + y+=text_height(p); + p=strchr(p,0)+1; + } + while (p[0]); + *pp=GetScreenAdr(); + *ss=_msize(*pp); + RestoreScreen(); + } + +void bott_disp_text(char *text) + { + if (text==0) text="Chybi popisek!!"; + zneplatnit_block(H_BOTTBAR); + if (bott_timer==NULL) + bott_timer=add_to_timer(TM_BOTT_MESSAGE,MSG_DELAY,1,bott_timer_draw); + else bott_timer->counter=MSG_DELAY; + bott_display=BOTT_TEXT; + if (bott_text!=NULL) free(bott_text); + bott_text=(char *)getmem(strlen(text)+1); + strcpy(bott_text,text); + } + +static void MaskPutPicture(int x, int y, char mask, word color, char blend, void *pic) + { + short *info=(short *)pic; + char *data=(char *)(info+3+256); + word *pos=GetScreenAdr()+x+y*scr_linelen2; + if (blend) color=color & 0xF7DE; + for (y=0;y>1; + else + pos[x]=color; + } + + +void bott_draw_rune(void **pp,long *ss) + { + int sel_zivel=showrune/10; + int sel_rune=showrune%10; + int maskrune=runes[sel_zivel]; + int i; + char buff[300]; + int spell=(sel_zivel*7+sel_rune)*3; + RedirectScreen(bott_clear()); + if (battle && cur_mode==MD_INBATTLE) put_picture(0,0,ablock(H_BATTLE_BAR)); + else put_picture(0,0,ablock(H_DESK)); + create_frame(70,20,280,50,1); + put_picture(378,0,ablock(H_RUNEBAR1+sel_zivel)); + for (i=0;i<7;i++) + if (!(maskrune & (1<counter=MSG_DELAY; + + } + +void bott_text_forever() + { + delete_from_timer(TM_BOTT_MESSAGE); + bott_timer=NULL; + } + +void bott_draw_proc(void **p,long *s) + { + switch (bott_display) + { + case BOTT_NORMAL:bott_draw_normal(p,s);break; + case BOTT_TEXT:bott_disp_text_proc(p,s);break; + case BOTT_FLETNA:bott_fletna_normal(p,s);break; + case BOTT_RUNA:bott_draw_rune(p,s);break; + } + } + +void bott_draw(char priority) + { + if (priority) + { + if (bott_display!=BOTT_NORMAL) + { + delete_from_timer(TM_BOTT_MESSAGE); + bott_timer=NULL; + bott_display=BOTT_NORMAL; + } + } + if (bott_display==BOTT_NORMAL) + zneplatnit_block(H_BOTTBAR); + } + +void bott_draw_fletna() + { + bott_display=BOTT_FLETNA; + zneplatnit_block(H_BOTTBAR); + } + +void draw_spell(int handle,int phase,int xicht) + { + int x,y,i; + word *w; + + if (bott_display!=BOTT_NORMAL) bott_draw(1); + for(i=0;i=10) + { + spell_handle=0; + spell_xicht=0; + } + } + put_picture(0,0,ablock(1)); + ukaz_kompas(0); + show_money(); + anim_sipky(0,-1); + draw_fx(); + memset(GetScreenAdr()+(SCREEN_OFFLINE-1)*scr_linelen2,0,1280); + memset(GetScreenAdr()+(SCREEN_OFFLINE+360)*scr_linelen2,0,1280); + } + +void display_spell_in_icone(int handle,int xicht) + { + spell_phase=0; + spell_handle=handle; + spell_xicht|=xicht; + } + +int fc_num(int anim_counter,int sector,char floor) + { + int mode; + TSECTOR *s; + TMAP_EDIT_INFO *m; + int basic; + + s=&map_sectors[sector]; + m=&map_coord[cur_sector]; + if (floor) + { + basic=s->floor; + mode=s->flags & 0xf; + } + else + { + basic=s->ceil; + mode=s->flags>>4; + } + + if (mode & 0x8) + return basic+(anim_counter % ((mode & 0x7)+1)); + switch (mode) + { + case 0: return basic; + case 1: return basic+((m->x+m->y+dirs[1]) & 0x1); + case 2: return basic+(dirs[1] & 0x1); + case 3: return basic+(dirs[1] & 0x1)*2+((m->x+m->y+(dirs[1]>>1)) & 0x1); + case 4: return basic+dirs[1]; + case 5: return basic+dirs[1]*2+((m->x+m->y+(dirs[1]>>1)) & 0x1); + } + return basic; + } + +int enter_tab[VIEW3D_Z+1][VIEW3D_X*2+1]= + {4,3,3,3,3,3,3,3,4, + 4,3,3,2,3,2,3,3,4, + 4,3,3,2,4,2,3,3,4, + 4,3,1,1,4,1,1,3,4, + 4,1,1,1,4,1,1,1,4}; + + + +void crt_minimap_itr(sector,smer,itrx,itry,automap) + { + static int sector_temp; + static long sideflags; + static short enter=0; + short savee; + + if (itrx==VIEW3D_X && itry==0) enter=0; + if (itrx<0 || itrx>VIEW3D_X*2 || itry>VIEW3D_Z) return; + if (minimap[itry][itrx]) return; + minimap[itry][itrx]=sector; + if (!set_halucination) map_coord[sector].flags|=automap & (itrx<=VIEW3D_X+1 && itrx>=VIEW3D_X-1) ; + if (itrx<=VIEW3D_X) + { + sector_temp=map_sectors[sector].step_next[dirs[0]]; + sideflags=map_sides[sector*4+dirs[0]].flags; + if (sector_temp && sideflags & 0x80 && enter>=0) + { + savee=enter; + enter=-enter_tab[itry][itrx]; + crt_minimap_itr(sector_temp,smer,itrx-1,itry,automap &(sideflags & 1)); + enter=savee; + } + } + if (itrx>=VIEW3D_X) + { + sector_temp=map_sectors[sector].step_next[dirs[2]]; + sideflags=map_sides[sector*4+dirs[2]].flags; + if (sector_temp && sideflags & 0x80 && enter<=0) + { + savee=enter; + enter=enter_tab[itry][itrx]; + crt_minimap_itr(sector_temp,smer,itrx+1,itry,automap &(sideflags & 1)); + enter=savee; + } + } + sector_temp=map_sectors[sector].step_next[dirs[1]]; + sideflags=map_sides[sector*4+dirs[1]].flags; + if (sector_temp && sideflags & 0x80) + { + savee=enter; + enter-=(enter>0)-(enter<0); + crt_minimap_itr(sector_temp,smer,itrx,itry+1,automap &(sideflags & 1)); + enter=savee; + } + } + + +void create_minimap(sector,smer) + { + memset(minimap,0,sizeof(minimap)); + dirs[1]=smer; + dirs[0]=(smer-1) & 3; + dirs[2]=(smer+1) & 3; + crt_minimap_itr(sector,smer,VIEW3D_X,0,1); + } + +static const float Inv2=0.5; +static const float Snapper=3<<22; + +__inline int toInt( float fval ) +{ + fval += Snapper; + return ( (*(int *)&fval)&0x007fffff ) - 0x00400000; +} + + +static void *check_autofade(void *image, char ceil, int dark) +{ + char *data=image; + if (data[5]==0x80) + { + word *xy=(word *)image; + if (mglob.map_autofadefc==1) + { + word *imgdata=xy+3; + int br=back_color>>11; + int bg=(back_color>>5) & 0x3F; + int bb=back_color & 0x1F; + int y; + + if (dark) br=bg=bb=0; + + for(y=0;y>11; + int g=(*imgdata>>5) & 0x3F; + int b=*imgdata & 0x1F; + r=toInt(r+factor*(br-r)); + g=toInt(g+factor*(bg-g)); + b=toInt(b+factor*(bb-b)); + *imgdata=(r<<11)|(g<<5)|b; + imgdata++; + } + } + } + xy[2]=xy[2] & 0xFF; + } + return image; +} + +#define draw_floor(s,celx,cely,dark) if (s->floor) draw_floor_ceil(celx,cely,0,check_autofade(ablock(num_ofsets[FLOOR_NUM]+fc_num(global_anim_counter,sector,1)),0,dark)); +#define draw_ceil(s,celx,cely,dark) if (s->ceil) draw_floor_ceil(celx,cely,1,check_autofade(ablock(num_ofsets[CEIL_NUM]+fc_num(global_anim_counter,sector,0)),1,dark)); +#define GET_OBLOUK(p) ((p->oblouk & 0xf)+(p->prim_anim>>4)) + +static int left_shiftup,right_shiftup; + +int draw_basic_floor(int celx,int cely,int sector) + { + TSECTOR *s; + int dark; + + s=&map_sectors[sector]; + dark=map_coord[sector].flags & MC_SHADING; + draw_floor(s,celx,cely,dark); + draw_ceil(s,celx,cely,dark); + return 0; + } + +static calc_item_shiftup(TITEM *it) + { + short *s; + char *c; + int y,x,xs,ys,t; + + t=0; + s=ablock(it->vzhled+face_arr[0]); + xs=s[0];ys=s[1];c=((char *)s)+PIC_FADE_PAL_SIZE; + c+=xs*ys-1;y=0; + while (yitems[i])!=0;i++) + { + TITEM *it=&glob_items[j-1]; + if (it->shiftup==0xff) it->shiftup=calc_item_shiftup(it); + draw_item2(celx,cely,v->xpos,v->ypos-it->shiftup,ablock(it->vzhled+face_arr[0]),i); + } + } + + +static int draw_basic_sector(int celx,int cely,int sector) + { + TSTENA *w,*q; + int obl; + + w=&map_sides[sector*4]; + q=&w[dirs[1]]; + obl=GET_OBLOUK(q); + if (celyflags & SD_LEFT_ARC && obl) + show_cel2(celx,cely,ablock(num_ofsets[OBL_NUM]+obl),0,0,1); + if (q->flags & SD_RIGHT_ARC && q->oblouk & 0x0f) + show_cel2(celx,cely,ablock(num_ofsets[OBL2_NUM]+obl),0,0,2); + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel2(celx,cely,ablock(num_ofsets[MAIN_NUM]+q->prim+(q->prim_anim>>4)),0,0,1+(q->oblouk & SD_POSITION)); + if (q->flags & SD_SEC_VIS && q->sec) + if (q->side_tag & SD_SHIFTUP) + { + if (cely!=0) + show_cel2(celx,cely-1,ablock(num_ofsets[MAIN_NUM]+q->sec+(q->sec_anim>>4)),0,0,1); + } + else + show_cel2(celx,cely,ablock(num_ofsets[MAIN_NUM]+q->sec+(q->sec_anim>>4)),q->xsec<<1,q->ysec<<1,0); + if (q->oblouk & 0x10) + draw_vyklenek(celx,cely,sector,dirs[1]); + } + if (celx<=0) + { + q=&w[dirs[0]]; + if (left_shiftup) + show_cel(celx,cely,ablock(num_ofsets[LEFT_NUM]+left_shiftup),0,0,2),left_shiftup=0; + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel(-celx,cely,ablock(num_ofsets[LEFT_NUM]+q->prim+(q->prim_anim>>4)),0,0,2+(q->oblouk & SD_POSITION)); + if (q->flags & SD_SEC_VIS && q->sec) + if (q->side_tag & SD_SHIFTUP) + if (celx!=0) left_shiftup=q->sec+(q->sec_anim>>4);else left_shiftup=0; + else if (q->flags & SD_SPEC) + show_cel(celx,cely,ablock(num_ofsets[LEFT_NUM]+q->sec+(q->sec_anim>>4)),0,0,2); + else + show_cel(celx,cely,ablock(num_ofsets[LEFT_NUM]+q->sec+(q->sec_anim>>4)),q->xsec<<1,q->ysec<<1,0); + } + if (celx>=0) + { + q=&w[dirs[2]]; + if (right_shiftup) + show_cel(celx,cely,ablock(num_ofsets[RIGHT_NUM]+right_shiftup),0,0,3),right_shiftup=0; + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel(celx,cely,ablock(num_ofsets[RIGHT_NUM]+q->prim+(q->prim_anim>>4)),0,0,3+(q->oblouk & SD_POSITION)); + if (q->flags & SD_SEC_VIS && q->sec) + if (q->side_tag & SD_SHIFTUP) + if (celx!=0) right_shiftup=q->sec+(q->sec_anim>>4);else right_shiftup=0; + else if (q->flags & SD_SPEC) + show_cel(celx,cely,ablock(num_ofsets[RIGHT_NUM]+q->sec+(q->sec_anim>>4)),0,0,3); + else + show_cel(celx,cely,ablock(num_ofsets[RIGHT_NUM]+q->sec+(q->sec_anim>>4)),500-(q->xsec<<1),q->ysec<<1,1); + } + return 0; + } + +static int draw_lodku(int celx,int cely) + { + if (cely==0) return 1; + show_cel2(celx,cely-1,ablock(H_LODKA0+(global_anim_counter & 7)),250,80,0); + return 0; + } + + +int p_place_table[4][5]= + { + {0,1,4,2,3}, + {1,2,4,3,0}, + {2,3,4,0,1}, + {3,0,4,1,2} + }; +int p_positions_x[5]={-32,32,32,-32,0}; +int p_positions_y[5]={32,32,-32,-32,0}; + +void draw_players(int sector,int dir,int celx,int cely) + { + if (map_coord[sector].flags & MC_DPLAYER) + { + int i; + THUMAN *p; + char freep[5]; + int j,d,pp=0,f; + + memset(freep,0,sizeof(freep)); + for(i=0,pp=0;isektor==sector && ((!p->lives && p->groupnum==0) || p->sektor!=viewsector)) + { + pp++; + d=(p->direction-dir)&0x3; + if (p->lives) + for(j=0;j<5 && freep[p_place_table[d][j]];j++); + else + for(j=4;j>=0 && freep[p_place_table[d][j]];j--); + if (j==5 || j==-1) break; + freep[f=p_place_table[d][j]]=i+1; + } + } + if (pp==1 && freep[f] & 1) + {pp=f+1&3;freep[pp]=freep[f];freep[f]=0;} + for(i=0;i<5;i++) + if ((j=freep[d=p_place_table[0][i]])!=0) + if (postavy[j-1].lives) + { + set_font(H_FLITT5,barvy_skupin[postavy[j-1].groupnum]); + draw_player(ablock(H_POSTAVY+j-1),celx,cely,p_positions_x[d],p_positions_y[d],HUMAN_ADJUST,postavy[j-1].jmeno); + } + else + draw_player(ablock(H_KOSTRA),celx,cely,p_positions_x[d],p_positions_y[d]-32,HUMAN_ADJUST,NULL); + + + } + } + + + +int draw_sloup_sector(celx,cely,sector) + { + TSTENA *w,*q; + int obl; + + w=&map_sides[sector*4]; + q=&w[dirs[1]]; + obl=GET_OBLOUK(q); + if (q->flags & SD_LEFT_ARC && q->oblouk) + show_cel2(celx,cely,ablock(num_ofsets[OBL_NUM]+obl),0,0,1); + if (q->flags & SD_RIGHT_ARC && q->oblouk) + show_cel2(celx,cely,ablock(num_ofsets[OBL2_NUM]+obl),0,0,2); + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel2(celx,cely,ablock(num_ofsets[MAIN_NUM]+q->prim+(q->prim_anim>>4)),0,0,1+(q->oblouk & SD_POSITION)); + if (celx<=0) + { + q=&w[dirs[0]]; + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel(-celx,cely,ablock(num_ofsets[LEFT_NUM]+q->prim+(q->prim_anim>>4)),0,0,2+(q->oblouk & SD_POSITION)); + } + if (celx>=0) + { + q=&w[dirs[2]]; + if (q->flags & SD_PRIM_VIS && q->prim) + show_cel(celx,cely,ablock(num_ofsets[RIGHT_NUM]+q->prim+(q->prim_anim>>4)),0,0,3+(q->oblouk & SD_POSITION)); + } + q=&w[dirs[1]]; + if (q->flags & SD_SEC_VIS && q->sec && cely!=0) + if (q->flags & SD_SPEC) + show_cel2(celx,cely-1,ablock(num_ofsets[MAIN_NUM]+q->sec+(q->sec_anim>>4)),0,0,2); + else + show_cel2(celx,cely-1,ablock(num_ofsets[MAIN_NUM]+q->sec+(q->sec_anim>>4)),(q->xsec<<1)+celx*(points[0][0][cely].x-points[0][0][cely-1].x)/2,q->ysec<<1,0); + return 0; + } + + +void swap_truesee(int ss) + { + int i; + for(i=0;i<4;i++) + { + TSTENA *s=map_sides+i+ss; + + if (s->flags & SD_TRUESEE) s->flags^=SD_PRIM_VIS | SD_SEC_VIS | SD_AUTOMAP; + } + } + +void draw_sector(int celx,int cely,int s) + { + int ss; + ss=s<<2; + if (true_seeing) swap_truesee(ss); + switch (map_sectors[s].sector_type) + { + case S_SSMRT: + case S_SLOUP: + case S_TELEPORT: + draw_sloup_sector(celx,cely,s); + draw_placed_items_normal(celx,cely,s,viewdir); + break; + case S_LODKA: + draw_basic_sector(celx,cely,s); + if (cely==0) draw_placed_items_normal(celx,cely,s,viewdir); + draw_lodku(celx,cely); + break; + default: + draw_basic_sector(celx,cely,s); + draw_placed_items_normal(celx,cely,s,viewdir); + break; + } + if (true_seeing) swap_truesee(ss); + } + +void back_clear(int celx,int color) + { + int x1,y1,x2,y2,xc; + y1=points[0][0][VIEW3D_Z].y+MIDDLE_Y+SCREEN_OFFLINE; + y2=points[0][1][VIEW3D_Z].y+MIDDLE_Y+SCREEN_OFFLINE; + x2=points[0][1][VIEW3D_Z].x+MIDDLE_X; + x1=-points[0][1][VIEW3D_Z].x+MIDDLE_X; + xc=(x2-x1+2)*celx; + x1=x1+xc-1; + x2=x2+xc; + if (x1<0) x1=0; + if (x2>640) x2=640; + if (x1sektor==viewsector && !(p->vlastnosti[VLS_KOUZLA] & SPL_BLIND)) return 0; + } + return 1; + } + +extern char folow_mode; + +static void zobraz_lodku(word *lodka, word *screen, int size) + { + int x; + while (size) + { + for (x=0;x<640 && size;x++) + { + if (*lodka!=0) screen[x]=*lodka; + lodka++; + size--; + } + screen+=scr_linelen2; + } + } +/* +static __inline void zobraz_lodku(word *data,word *scr,int _size) + { + __asm + { + mov ecx,_size + mov esi,data + mov edi,scr + add esi,6 +lp1:lodsw + or ax,ax + jz skp + mov [edi],ax +skp: add edi,2h + dec ecx + jnz lp1 + } + } +*/ + +static void trace_for_bgr(int dir) + { + int s,i; + static int olddist=0; + static int olddir=0; + TSTENA *ss; + + bgr_handle=0; + bgr_distance=-1; + for(i=0,s=0;iflags & SD_PRIM_VIS && !ss->prim) + { + bgr_distance=i-1; + bgr_handle=num_ofsets[BACK_NUM]+dir; + break; + } + } + if (olddist!=bgr_distance || olddir!=dir) + { + if (bgr_distance==-1) + { + word *w=GetScreenAdr();int i=scr_linelen2*480; + do {if (*w>=NOSHADOW(0)) *w=back_color;w++;} while(--i); + } + zneplatnit_block(H_BGR_BUFF); + } + olddist=bgr_distance; + olddir=dir; + } + + +void render_scene(sector,smer) + { + int i,j,s; + + cancel_render=0;see_monster=0; + destroy_fly_map(); + build_fly_map(); + if (set_blind() && cur_mode!=MD_END_GAME && !folow_mode) + { + clear_buff(NULL,0,360); + return; + } + if (set_halucination) + { + sector=hal_sector; + smer=hal_dir; + } + cur_sector=sector; + create_minimap(sector,smer); +// trace_for_bgr(smer); + i=VIEW3D_Z-1; + s=minimap[i][VIEW3D_X]; + if (s && !map_sectors[s].ceil) clear_buff(ablock(H_BGR_BUFF),back_color,360); + else clear_buff(ablock(H_BGR_BUFF),back_color,80); + for(i=-VIEW3D_X+1;i=0;i--) + { + word *p; + + p=minimap[i]; + left_shiftup=0;right_shiftup=0; + for(j=VIEW3D_X-1;j>=0;j--) + { + int s2; + if ((s=p[VIEW3D_X+j])!=0) + { + if (map_coord[s].flags & MC_SHADING) secnd_shade=1; else secnd_shade=0; + draw_basic_floor(j,i,s); + if (map_sides[(s<<2)+smer].flags & SD_TRANSPARENT) + { + s2=map_sectors[s].step_next[smer]; + draw_mob(s2,smer,j,i,1); + } + draw_sector(j,i,s); + } + if (j && (s=p[VIEW3D_X-j])) + { + if (map_coord[s].flags & MC_SHADING) secnd_shade=1; else secnd_shade=0; + draw_basic_floor(-j,i,s); + if (map_sides[(s<<2)+smer].flags & SD_TRANSPARENT) + { + s2=map_sectors[s].step_next[smer]; + draw_mob(s2,smer,-j,i,1); + } + draw_sector(-j,i,s); + } + } + for(j=VIEW3D_X-1;j>=0;j--) + { + if ((s=p[VIEW3D_X+j])!=0) + { + if (map_coord[s].flags & MC_SHADING) secnd_shade=1; else secnd_shade=0; + draw_players(s,viewdir,j,i); + draw_mob(s,viewdir,j,i,0); + draw_fly_items(j,i,s,viewdir); + draw_spectxtrs(s,j,i); + } + if (j && (s=p[VIEW3D_X-j])) + { + if (map_coord[s].flags & MC_SHADING) secnd_shade=1; else secnd_shade=0; + draw_players(s,viewdir,-j,i); + draw_mob(s,viewdir,-j,i,0); + draw_fly_items(-j,i,s,viewdir); + draw_spectxtrs(s,-j,i); + } + } + do_events(); + if (cancel_render) return; + } + calc_spectxtrs(); + if (lodka) zobraz_lodku(ablock(H_LODKA),LODKA_POS,LODKA_SIZ); + } + +void debug_print() + { + char s[256]; + static char indx=50; + static int counter=0; + + sprintf(s,"battle: %d waiting: %d lhit: %3d ldef: %3d dostal: %3d magic: %3d lives: %3d wpn: %d", + battle, neco_v_pohybu, dhit, ddef, ddostal, dmzhit, dlives, vybrana_zbran ); + trans_bar(0,17,640,15,0); + position(0,17);set_font(H_FBOLD,0x3ff); + if (debug_text!=NULL) + { + outtext(debug_text); + counter++; + if (counter==100) + { + counter=0; + debug_text=NULL; + } + } + else outtext(s); + if (dsee) indx--; + if (!indx) + { + dsee=0; + indx=10; + } + + } + +void redraw_scene() + { + if (norefresh) return; + if (one_buffer) RedirectScreenBufferSecond(); + render_scene(viewsector,viewdir); + if (cancel_render) return; + if (running_anm) klicovani_anm(GetBuffer2nd()+SCREEN_OFFSET,anim_render_buffer,anim_mirror); + update_mysky(); + schovej_mysku(); + if (one_buffer) RestoreScreen(); + OutBuffer2nd(); + if (battle || (game_extras & EX_ALWAYS_MINIMAP)) draw_medium_map(); + if (show_debug) debug_print(); + other_draw(); + ukaz_mysku(); + global_anim_counter++; + send_message(E_KOUZLO_ANM); + } + +void refresh_scene() + { + redraw_scene(); + if (!cancel_render && !norefresh) + { + showview(0,0,0,0); + calc_game(); + if (autoopenaction==1) {go_book(0,0,0,0,0);autoopenaction=0;} + } + } + +typedef struct fx_play + { + int x,y,phase; + struct fx_play *next; + }FX_PLAY; + +static FX_PLAY *fx_data=NULL; + +void draw_fx() + { + word *c; + FX_PLAY *fx; + FX_PLAY **last; + + if (fx_data==NULL) return; + fx=fx_data;last=&fx_data; + c=ablock(H_FX); + while (fx!=NULL) + { + put_8bit_clipped(c,GetScreenAdr()+fx->x+fx->y*scr_linelen2,fx->phase*16,c[0],16); + if (++fx->phase>14) + { + *last=NULL; + free(fx); + return; + } + last=&(fx->next); + fx=*last; + } + } + + +void play_fx(int x,int y) + { + FX_PLAY *fx; + + fx=New(FX_PLAY); + fx->next=fx_data; + fx->x=x; + fx->y=y; + fx->phase=0; + fx_data=fx; + } + +void play_fx_at(int where) + { + static word polex[]={313,290,362}; + static word poley[]={1,1,1}; + + play_fx(polex[where],poley[where]); + } + +void display_ver(int x,int y,int ax,int ay) + { + char *ver="Br ny Skeldalu version "VERSION" (C)1998"; + set_font(H_FTINY,RGB555(31,31,31));set_aligned_position(x,y,ax,ay,ver); + outtext(ver);showview(0,0,0,0); + } diff --git a/GAME/CHARGEN.C b/GAME/CHARGEN.C new file mode 100644 index 0000000..cecfb0f --- /dev/null +++ b/GAME/CHARGEN.C @@ -0,0 +1,908 @@ +//CHARACTER GENERATOR +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include + +//there is defined procedures from source "INV.C" + +void display_items_wearing(THUMAN *h); +void inv_display_vlastnosti();; +extern void (*inv_redraw)(); +void write_human_big_name(char *c); + +#define MSG_COLOR1 RGB555(30,30,23) + + +#define MAX_XICHTS 8 +#define MAX_CHARS 6 + +#define XICHT_STEP 40 + +#define INV_DESK 266 +#define INV_DESK_Y (SCREEN_OFFLINE) +#define INV_DESC_X 285 +#define INV_DESC_Y (SCREEN_OFFLINE+20) +#define HUMAN_X 40 +#define HUMAN_Y 328 + + +#define X_SKIP_X 64 +#define X_SKIP_Y 85 + +typedef struct staty + { + int zivl; + int zivh; + int manl; + int manh; + int konl; + int konh; + int akc; + }T_STATY; + +static T_STATY cur_stats; + +word color_butt_on[]={0,RGB555(31,27,4),RGB555(30,26,4),RGB555(29,25,4)}; +word color_butt_off[]={0,RGB555(10,10,10),RGB555(10,10,10),RGB555(10,10,10)}; + + +typedef struct vlasts + { + int sill; + int silh; + int smgl; + int smgh; + int pohl; + int pohh; + int obrl; + int obrh; + int hpreg; + int mpreg; + int vpreg; + }T_VLASTS; + +static T_VLASTS cur_vls; +static T_VLASTS rohy[9]= + { + {17,22, 5,10,17,22, 9,14, 3, 2, 3}, + {13,18,10,15,20,25, 5,10, 3, 3, 2}, + { 9,14,15,20,17,22, 9,14, 3, 3, 2}, + { 5,10,20,25,13,18,13,18, 2, 4, 2}, + { 9,14,15,20, 9,14,17,22, 2, 3, 2}, + {13,18,10,15, 5,10,20,25, 2, 2, 4}, + {17,22, 5,10, 9,14,17,22, 3, 1, 2}, + {20,25, 0, 5,13,18,13,18, 4, 1, 2}, + {12,17,12,17,12,17,12,17, 2, 2, 2}, + }; + +#define CALC_DIFF(x,y,angl) ((x)+(((((y)-(x))<<4)*((angl)<<4)/720+8)>>4)) +#define CALC_DIFF2(x,y,pol) ((x)+(((((y)-(x))<<4)*((pol)<<4)/(PERLA_MAXPOLOMER<<4)+8)>>4)) +#define DIFF_RAND(x,y) ((x)+rnd((y)-(x)+1)) + +#define MAX_RACES 5 +static char women[MAX_XICHTS]={0,0,0,0,1,1,1,1}; +static char poradi[MAX_XICHTS]={0,2,3,4,1,5,6,7}; +static char disable[MAX_XICHTS]; +static int cur_edited=0; +static int cur_angle=90; +static int cur_polomer=0; +static int cur_xicht=-1; +static char shut_downing_text=0; +static int save_values[POCET_POSTAV][2]; +static char del_mode=0; +static char was_enter=0; + + +#define PERLA_STRED_X (INV_DESK+189) +#define PERLA_STRED_Y (INV_DESK_Y+217) + + +#define PERLA_POLOMER cur_polomer +#define PERLA_MAXPOLOMER 75 +short *pod_perlou=NULL; +short pod_perlou_x=0; +short pod_perlou_y=0; +char *error_text=NULL; + + + +char select_xicht(int id,int xa,int ya,int xr,int yr); +char vol_vlastnosti(int id,int xa,int ya,int xr,int yr); +char go_next_page(int id,int xa,int ya,int xr,int yr); +char vls_click(int id,int xa,int ya,int xr,int yr); +char view_another_click2(int id,int xa,int ya,int xr,int yr); +//char edit_another_click(int id,int xa,int ya,int xr,int yr); +char edit_another_click2(int id,int xa,int ya,int xr,int yr); +char gen_exit_editor(int id,int xa,int ya,int xr,int yr); + +void zobraz_staty(T_VLASTS *st); + +#define CLK_PAGE1 6 + + +static T_CLK_MAP clk_page1[]= + { + {0,28+INV_DESK,18+INV_DESK_Y,334+INV_DESK,55+INV_DESK_Y,select_xicht,2,-1}, + {0,78+INV_DESK,97+INV_DESK_Y,314+INV_DESK,340+INV_DESK_Y,vol_vlastnosti,2+1,-1}, + {-1,520,378,639,479,go_next_page,2,-1}, + //{-1,54,378,497,479,edit_another_click,2+8,-1}, + {2,0,0,639,479,gen_exit_editor,8,-1}, + {0,0,0,639,479,empty_clk,0xff,-1}, + }; + +#define CLK_PAGE2 5 + +static T_CLK_MAP clk_page2[]= + { + {-1,INV_DESK,INV_DESK_Y,639,378,vls_click,2,-1}, + {-1,520,378,639,479,go_next_page,2,-1}, + {-1,54,378,497,479,view_another_click2,2,-1}, + {1,0,0,639,479,gen_exit_editor,8,-1}, + {0,0,0,639,479,empty_clk,0xff,-1}, + }; +#define CLK_PAGE3 4 + +/*static T_CLK_MAP clk_page3[]= + { + {-1,520,378,639,479,go_next_page,2,-1}, + {-1,54,378,497,479,view_another_click2,2+8,-1}, + {0,0,0,639,479,edit_another_click2,8,-1}, + {0,0,0,639,479,empty_clk,0xff,-1}, + }; +*/ + + +#define H_GENERACE (H_MENUS_FREE+100) +#define H_GEN_PERLA (H_MENUS_FREE+101) +#define H_GEN_TOPBAR (H_MENUS_FREE+102) +#define H_GEN_OKBUTT (H_MENUS_FREE+103) +#define H_GEN_CHARGEN (H_MENUS_FREE+104) +#define H_GEN_CHARGENB (H_MENUS_FREE+105) +#define H_GEN_CHARGENM (H_MENUS_FREE+106) +#define H_GEN_XICHTY (H_MENUS_FREE+107) +#define H_GEN_POSTAVY (H_GEN_XICHTY+MAX_XICHTS) + +TDREGISTERS char_gen_reg[]= + { + {H_GENERACE,"postavy.pcx",pcx_15bit_decomp,SR_BGRAFIKA}, + {H_GEN_PERLA,"perla.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_GEN_TOPBAR,"topbar_p.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_GEN_CHARGEN,"chargen.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_GEN_CHARGENB,"chargenb.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_GEN_CHARGENM,"chargenm.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + }; + +#define BOTT 378 +#define LEFT 520 + +char *b_texty[4]; +char b_disables; + +void displ_button(char disable,char **text) + { + int posy[]={0,18,37,55}; + int sizy[]={18,20,20,21}; + int i; + + set_font(H_FTINY,0); + put_picture(LEFT,BOTT,ablock(H_GEN_CHARGEN)); + for(i=0;i<4;i++) + { + if (disable & 1) + { + put_8bit_clipped(ablock(H_GEN_CHARGENB),(392+posy[i])*scr_linelen2+524+GetScreenAdr(),posy[i],96,sizy[i]); + font_color(color_butt_off); + } + else + { + font_color(color_butt_on); + } + disable>>=1; + set_aligned_position(LEFT+50,BOTT+14+13+i*19,1,2,*text); + outtext(*text); + text++; + } + } +static void draw_other_bar() + { + int i; + word *bbar=ablock(H_BOTTBAR); + word *screen=GetScreenAdr()+(480-102)*scr_linelen2; + for (i=0;i<102;i++,screen+=scr_linelen2,bbar+=scr_linelen2) memcpy(screen,bbar,scr_linelen); + //put_8bit_clipped(ablock(H_GEN_OKBUTT),378*640+520+screen,0,120,102); + displ_button(b_disables,b_texty); + put_picture(0,0,ablock(H_GEN_TOPBAR)); + zobraz_staty(&cur_vls); + } + + +static void display_character(THUMAN *p,char i) + { + word *w; + put_picture(4,SCREEN_OFFLINE,ablock(H_IOBLOUK)); + if (p->used) + { + w=ablock(H_GEN_POSTAVY+(p->xicht)); + put_picture(HUMAN_X+30,HUMAN_Y-w[1],w); + } + if (i) draw_other_bar(); + } +static void zobraz_error_text() + { + if (error_text!=NULL) + { + trans_bar(0,362,640,16,0); + set_font(H_FONT6,RGB555(31,31,0)); + position(10,364);outtext(error_text); + } + } + + + + +static void vypocet_perly(int angle,int xp,int yp,int *x,int *y) + { + float xr,yr; + float rad; + + rad=angle*3.14159265f/180; + xr=(float)cos(rad)*PERLA_POLOMER; + yr=(float)sin(rad)*PERLA_POLOMER; + *x=(int)xr+PERLA_STRED_X; + *y=PERLA_STRED_Y-(int)yr; + x[0]-=xp>>1; + y[0]-=yp>>1; + } + +static void zobraz_perlu(void) + { + word *perla; + int x,y; + word *scr,*sss; + char *p; + word *b; + int xs,ys,xxs; + + alock(H_GEN_PERLA); + perla=ablock(H_GEN_PERLA); + if (pod_perlou==NULL) + { + pod_perlou=getmem(perla[0]*perla[1]*2+6); + } + vypocet_perly(cur_angle,perla[0],perla[1],&x,&y); + xs=perla[0];ys=perla[1]; + get_picture(x,y,xs,ys,pod_perlou); + sss=x+scr_linelen2*y+GetScreenAdr(); + p=(char *)(perla+256+3); + b=perla+3; + for(;ys>0;ys--) + { + scr=sss; + for(xxs=0;xxs>1; + scr++;p++; + } + sss+=scr_linelen2; + } + //put_picture(x,y,perla); + pod_perlou_x=x; + pod_perlou_y=y; + aunlock(H_GEN_PERLA); + } + +static void schovej_perlu(void) + { + put_picture(pod_perlou_x,pod_perlou_y,pod_perlou); + } + +static void vypocet_vlastnosti(int angle,T_VLASTS *vls) + { + T_VLASTS *low,*hi; + div_t rm; + int p,test; + + rm=div(angle,45); + p=rm.quot; + low=rohy+p;p++;if (p>=8) p=0; + hi=rohy+p; + test=CALC_DIFF(8,12,44); + vls->sill=CALC_DIFF(low->sill,hi->sill,rm.rem); + vls->silh=CALC_DIFF(low->silh,hi->silh,rm.rem); + vls->smgl=CALC_DIFF(low->smgl,hi->smgl,rm.rem); + vls->smgh=CALC_DIFF(low->smgh,hi->smgh,rm.rem); + vls->obrl=CALC_DIFF(low->obrl,hi->obrl,rm.rem); + vls->obrh=CALC_DIFF(low->obrh,hi->obrh,rm.rem); + vls->pohl=CALC_DIFF(low->pohl,hi->pohl,rm.rem); + vls->pohh=CALC_DIFF(low->pohh,hi->pohh,rm.rem); + vls->hpreg=CALC_DIFF(low->hpreg,hi->hpreg,rm.rem); + vls->mpreg=CALC_DIFF(low->mpreg,hi->mpreg,rm.rem); + vls->vpreg=CALC_DIFF(low->vpreg,hi->vpreg,rm.rem); + low=&rohy[8];hi=vls;rm.rem=PERLA_POLOMER; + vls->sill=CALC_DIFF2(low->sill,hi->sill,rm.rem); + vls->silh=CALC_DIFF2(low->silh,hi->silh,rm.rem); + vls->smgl=CALC_DIFF2(low->smgl,hi->smgl,rm.rem); + vls->smgh=CALC_DIFF2(low->smgh,hi->smgh,rm.rem); + vls->obrl=CALC_DIFF2(low->obrl,hi->obrl,rm.rem); + vls->obrh=CALC_DIFF2(low->obrh,hi->obrh,rm.rem); + vls->pohl=CALC_DIFF2(low->pohl,hi->pohl,rm.rem); + vls->pohh=CALC_DIFF2(low->pohh,hi->pohh,rm.rem); + vls->hpreg=CALC_DIFF2(low->hpreg,hi->hpreg,rm.rem); + vls->mpreg=CALC_DIFF2(low->mpreg,hi->mpreg,rm.rem); + vls->vpreg=CALC_DIFF2(low->vpreg,hi->vpreg,rm.rem); + } + +/*static void vypocet_statu(T_VLASTS *vls,T_STATY *sts) + { + sts->zivl=vls->sill*3/2; + sts->zivh=vls->silh*3/2; + sts->manl=vls->smgl*2; + sts->manh=vls->smgh*2; + sts->konl=vls->obrl*2; + sts->konh=vls->obrh*2; + sts->akc=(((vls->pohl+vls->pohh)/2)+14)/15; + } +*/ + +static void zobraz_staty(T_VLASTS *st) + { + char s[100]; + + set_font(H_FTINY,0);font_color(color_topbar); + sprintf(s,texty[2],st->sill,st->silh); + position(230,2);outtext(s); + sprintf(s,texty[3],st->smgl,st->smgh); + position(330,2);outtext(s); + sprintf(s,texty[4],st->pohl,st->pohh); + position(430,2);outtext(s); + sprintf(s,texty[5],st->obrl,st->obrh); + position(530,2);outtext(s); + } + + +void redraw_generator(char show) + { + T_STATY z; + int i; + memset(&z,20,sizeof(z)); + schovej_mysku(); + put_picture(INV_DESK,SCREEN_OFFLINE,ablock(H_GENERACE)); + if (cur_xicht==-1) + { + put_picture(4,SCREEN_OFFLINE,ablock(H_IOBLOUK)); + bott_draw(1); + draw_other_bar(); + } + else display_character(postavy+cur_edited,1); + zobraz_error_text(); + zobraz_perlu(); + for(i=0;iused=1; + h->xicht=xicht; + h->vlastnosti[VLS_MAXHIT]=1; + h->vlastnosti[VLS_KONDIC]=1; + h->lives=1; + h->kondice=0; + h->mana=0; + h->sektor=viewsector; + h->groupnum=1; + h->jidlo=1; + h->voda=1; + h->bonus=0; + h->spell=0; + } + +static char select_xicht(int id,int xa,int ya,int xr,int yr) + { + int i,j,k; + char s[20]; + + i=xr/XICHT_STEP; + j=xr%XICHT_STEP; + if (j>27) return 0; + k=poradi[i]; + if (disable[k]) return 1; + memset(disable,0,sizeof(disable)); + set_xicht(cur_edited,cur_xicht=k); + postavy[cur_edited].female=women[i]; + b_disables=0x6; + if (was_enter) send_message(E_KEYBOARD,13); + else + { + strcpy(postavy[cur_edited].jmeno,texty[160+i]); + send_message(E_KEYBOARD,27); + was_enter=0; + } + sprintf(s,XICHT_NAME,k); + def_handle(H_XICHTY+cur_edited,s,pcx_8bit_decomp,SR_BGRAFIKA); + sprintf(s,CHAR_NAME,k); + def_handle(H_POSTAVY+cur_edited,s,pcx_8bit_decomp,SR_BGRAFIKA); + for(j=0;jpod_perlou_x+pod_perlou[0] || ya>pod_perlou_y+pod_perlou[1] ) + { + cancel=1; + return 0; + } + else cancel=0; + if (cancel) return 0; + xr=xa-PERLA_STRED_X; + yr=-(ya-PERLA_STRED_Y); + a=(int)(atan2((double)yr,(double)xr)*180/3.14159265); + cur_polomer=(int)sqrt(xr*xr+yr*yr); + if (cur_polomer>PERLA_MAXPOLOMER) cur_polomer=PERLA_MAXPOLOMER; + xa=pod_perlou_x; + ya=pod_perlou_y; + schovej_mysku(); + schovej_perlu(); + if (a<0) a+=360; + vypocet_vlastnosti(a,&cur_vls); + cur_angle=a; + zobraz_perlu(); + ukaz_mysku(); + update_mysky(); + showview(pod_perlou_x,pod_perlou_y,pod_perlou[0],pod_perlou[1]); + showview(xa,ya,pod_perlou[0],pod_perlou[1]); + put_picture(0,0,ablock(H_GEN_TOPBAR)); + zobraz_staty(&cur_vls); + showview(250,0,640,17); + return 1; + } + +static int edit_task=-1; + +static void edit_name() + { + if (shut_downing_text) return; + curcolor=0;bar(120,2,120+104,16); + edit_task=add_task(16384,type_text_v2,postavy[cur_edited].jmeno,120,2,104, + sizeof(postavy[cur_edited].jmeno)-1,H_FONT6,RGB555(31,31,0),edit_name); + } + +static void stop_edit_name() + { + shut_downing_text=1;send_message(E_KEYBOARD,13); + task_sleep(NULL); + if (edit_task>0 && is_running(edit_task)) + shut_down_task(edit_task); + shut_downing_text=0; + } + +/*static char edit_another_click(int id,int xa,int ya,int xr,int yr) + { + short *w; + + id,xa,ya,xr,yr; + w=ablock(H_OKNO); + id=xr/w[0]; + if (!postavy[id].used) return 0; + shut_downing_text=1; + send_message(E_KEYBOARD,13); + shut_downing_text=0; + save_values[cur_edited][0]=cur_angle; + save_values[cur_edited][1]=cur_polomer; + select_player=cur_edited=id; + cur_angle=save_values[cur_edited][0]; + cur_polomer=save_values[cur_edited][1]; + vypocet_vlastnosti(cur_angle,&cur_vls); + cur_xicht=postavy[cur_edited].xicht; + edit_name(); + bott_draw(1); + redraw_generator(); + return 1; + } +*/ + + +static void def_entries() + { + int i; + int s; + TDREGISTERS *p; + + s=sizeof(char_gen_reg)/sizeof(TDREGISTERS); + p=char_gen_reg; + for(i=0;ih_num,p->name,p->proc,p->path); + for(i=0;iused=1; + h->groupnum=1; + v=h->stare_vls; + v[VLS_SILA]=DIFF_RAND(cur_vls.sill,cur_vls.silh); + v[VLS_SMAGIE]=DIFF_RAND(cur_vls.smgl,cur_vls.smgh); + v[VLS_POHYB]=DIFF_RAND(cur_vls.pohl,cur_vls.pohh); + v[VLS_OBRAT]=DIFF_RAND(cur_vls.obrl,cur_vls.obrh); + v[VLS_HPREG]=cur_vls.hpreg; + v[VLS_MPREG]=cur_vls.mpreg; + v[VLS_VPREG]=cur_vls.vpreg; +// v[VLS_THIEF]=cur_vls.vpreg; + h->lives=v[VLS_MAXHIT]=(v[VLS_SILA]*3+v[VLS_POHYB])/2; + h->mana=v[VLS_MAXMANA]=v[VLS_SMAGIE]*2; + h->kondice=v[VLS_KONDIC]=v[VLS_OBRAT]*2; + v[VLS_OBRAN_L]=1; + v[VLS_OBRAN_H]=2; + v[VLS_UTOK_L]=1; + v[VLS_UTOK_H]=2; + prepocitat_postavu(h); + h->inv_size=6; + h->level=1; + h->exp=0; + h->bonus=5; + h->jidlo=MAX_HLAD(h); + h->voda=MAX_ZIZEN(h); + h->mana_battery=32767; + //postava je vygenerovana + } + +static void redraw_page3() + { + update_mysky(); + schovej_mysku(); + curcolor=0; + inv_display_vlastnosti(); + display_character(postavy+cur_edited,1); + write_human_big_name(postavy[cur_edited].jmeno); + draw_other_bar(); + displ_button(b_disables,b_texty); + ukaz_mysku(); + showview(0,0,0,0); + inv_redraw=redraw_page3; + } + + +static void redraw_svitek() + { + if (postavy[cur_edited].bonus==0) + { + char mode; + mode=7; + if (postavy[charmin-1].used) mode&=~2; + if (!postavy[charmax-1].used) mode&=~1; + if (!del_mode) mode&=~4; + b_disables=mode; + redraw_page3(); + return; + } + update_mysky(); + schovej_mysku(); + curcolor=0; + bar(0,16,30,16+360); + bar(620,16,640,16+360); + inv_display_vlastnosti(); + display_character(postavy+cur_edited,0); +// display_items_wearing(human_selected); +// write_pocet_sipu(); +// display_rings(); + zobraz_error_text(); + displ_button(b_disables,b_texty); + ukaz_mysku(); + showview(0,0,0,0); + inv_redraw=redraw_svitek; + } + + +static char validate_character(THUMAN *h) + { + if (h->jmeno[0]==0) error_text=texty[111]; + else error_text=NULL; + return error_text==NULL; + } + +/*static char edit_another_click2(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + cur_edited=select_player; + schovej_mysku(); + edit_name(); + draw_other_bar(); + send_message(E_CLOSE_GEN,0); + ukaz_mysku(); + update_mysky(); + return 1; + } + */ +static void empty_proc() + { + } + +char potvrzeno(char *text,void (*redraw)()) + { + int i; + unwire_proc=empty_proc; + stop_edit_name(); + i=message(2,0,1,texty[118],text,texty[114],texty[115])==0; + redraw(); + edit_name(); + return i; + } + +static char view_another_click2(int id,int xa,int ya,int xr,int yr) + { + short *w; + + id,xa,ya,xr,yr; + w=ablock(H_OKNO); + id=xr/w[0]; + if (!(~b_disables & 0x3)) return 1; + if (!postavy[id].used) return 0; + shut_downing_text=1;send_message(E_KEYBOARD,13); + shut_downing_text=0; + select_player=id; + bott_draw(1); + human_selected=postavy+id; + cur_edited=id; + edit_name(); + redraw_page3(); + if (del_mode) + if (potvrzeno(texty[117],redraw_page3)) + { + del_mode=0; + postavy[cur_edited].used=0; + disable[postavy[cur_edited].xicht]=0; + send_message(E_CLOSE_GEN,0); + } + return 0; + } + +void effect_show(va_list args) + { + int i; + schovej_mysku(); + for(i=0;i<12;i++) + { + showview(0,240-i*20-20,640,20); + showview(0,240+(i*20),640,20); + task_wait_event(E_TIMER); + } + ukaz_mysku(); + } + + +static void enter_reaction(EVENT_MSG *msg,void **unused) + { + unused; + if (msg->msg==E_KEYBOARD) + { + if (*(char *)msg->data==13 && !shut_downing_text) + { + send_message(E_KEYBOARD,13); + bott_draw(1); + redraw_generator(1); + msg->msg=-1; + } + was_enter=1; + } + } + +static void enter_reaction2(EVENT_MSG *msg,void **unused) + { + unused; + if (msg->msg==E_KEYBOARD && *(char *)msg->data==13 && !shut_downing_text && ~b_disables & 0x3) + { + send_message(E_KEYBOARD,13); + bott_draw(1); + redraw_page3(); + msg->msg=-1; + } + } + + +char gen_exit_editor(int id,int xa,int ya,int xr,int yr) + { + xa,ya,xr,yr,id; + + if (del_mode==1) + { + del_mode=0; + mouse_set_default(H_MS_DEFAULT); + b_disables&=~0x4; + redraw_svitek(); + return 1; + } + unwire_proc=empty_proc; + shut_downing_text=1;send_message(E_KEYBOARD,13);shut_downing_text=0; + if (message(2,0,1,texty[118],texty[113],texty[114],texty[115])==0) + { + send_message(E_CLOSE_GEN,255); + } + else + { + if (id==2)redraw_generator(1); + else redraw_svitek(); + edit_name(); + } + return 1; + } + +char enter_generator() + { + int i; + char rep=0; + + znova: + del_mode=0; + stop_edit_name(); + b_texty[0]=texty[170]; + b_texty[1]=texty[171]; + b_texty[2]=texty[172]; + b_texty[3]=texty[173]; + def_entries(); + curcolor=0;bar(0,0,639,479); + cur_angle=315; + cur_edited=0; + memset(postavy,0,sizeof(postavy)); + memset(disable,0,sizeof(disable)); + memset(save_values,0,sizeof(save_values)); + do + { + mouse_set_default(H_MS_DEFAULT); + cur_angle=save_values[cur_edited][0]; + cur_polomer=save_values[cur_edited][1]; + set_xicht(cur_edited,cur_xicht=-1); + select_player=-1; + memset(&cur_stats,0,sizeof(cur_stats)); + vypocet_vlastnosti(cur_angle,&cur_vls); + b_disables=0x7; + redraw_generator(rep);if (!rep)effect_show(NULL);rep=1; + edit_name(); + change_click_map(clk_page1,CLK_PAGE1); + was_enter=0; + do + { + send_message(E_ADD,E_KEYBOARD,enter_reaction); + i=*(char *)task_wait_event(E_CLOSE_GEN); + send_message(E_DONE,E_KEYBOARD,enter_reaction); + if (i==3 && potvrzeno(texty[116],redraw_generator)) goto znova; + if (i==255) return 1; + } + while (cur_xicht==-1 || i==3); + send_message(E_KEYBOARD,13); + save_values[cur_edited][0]=cur_angle; + save_values[cur_edited][1]=cur_polomer; + cur_xicht=0; + error_text=NULL; + generuj_postavu(postavy+cur_edited); + human_selected=postavy+cur_edited; + b_disables=0x7; + do + { + redraw_svitek(); + change_click_map(clk_page2,CLK_PAGE2); + do + { + send_message(E_ADD,E_KEYBOARD,enter_reaction2); + i=*(char *)task_wait_event(E_CLOSE_GEN); + send_message(E_DONE,E_KEYBOARD,enter_reaction2); + if (i==3 && potvrzeno(texty[116],redraw_svitek)) goto znova; + if (i==2) + { + del_mode=1; + mouse_set_default(H_MS_WHO); + b_disables|=0x4; + redraw_svitek(); + i=3; + } + } + while (i==3); + mouse_set_default(H_MS_DEFAULT); + del_mode=0; + send_message(E_KEYBOARD,13); + if (i==255) return 1; + if (validate_character(postavy+cur_edited)) + for(cur_edited=0;postavy[cur_edited].used;cur_edited++); + } + while (error_text!=NULL); + stop_edit_name(); + } + while (i!=1); + disable_click_map(); + schovej_mysku(); + curcolor=0; + bar(0,0,639,479); + showview(0,0,0,0); + ukaz_mysku(); + for(i=0;i<3;i++) + { + if (postavy[i].vlastnosti[VLS_SILA]>20) postavy[i].stare_vls[VLS_UTOK_H]++; + if (postavy[i].vlastnosti[VLS_OBRAT]>20) postavy[i].stare_vls[VLS_OBRAN_H]++; + } + return 0; + } + + + + + + + + + diff --git a/GAME/CHARGEN2.C b/GAME/CHARGEN2.C new file mode 100644 index 0000000..0139e85 --- /dev/null +++ b/GAME/CHARGEN2.C @@ -0,0 +1,344 @@ +//CHARACTER GENERATOR + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include + +//there is defined procedures from source "INV.C" + +void display_items_wearing(THUMAN *h); + + +#define MAX_XICHTS 8 +#define MAX_CHARS 3 + +#define INV_DESK 266 +#define INV_DESC_X 285 +#define INV_DESC_Y (SCREEN_OFFLINE+20) +#define HUMAN_X 40 +#define HUMAN_Y 328 + + +#define X_SKIP_X 64 +#define X_SKIP_Y 85 + +typedef struct staty + { + char zivl; + char zivh; + char manl; + char manh; + char konl; + char konh; + char akc; + }T_STATY; + +#define MAX_RACES 5 +static char women[MAX_XICHTS]={0,1,0,0,0,1,0,0};//,0,0}; +static int cur_edited=0; +static int cur_xicht=-1; +static int cur_page=1; +static int loc_select=-1; + +#define CLK_PAGE1 3 + + + +static T_CLK_MAP clk_page1[]= + { + + }; + +static void display_character(THUMAN *p) + { + word *w; + put_picture(4,SCREEN_OFFLINE,ablock(H_IOBLOUK)); + if (p->used) + { + w=ablock(hl_ptr+MAX_XICHTS+(p->xicht)); + put_picture(HUMAN_X+30,HUMAN_Y-w[1],w); + } + } +/* +static void display_all_xichts() + { + int i,a,x,y; + + a=0; + x=INV_DESC_X;y=INV_DESC_Y; + for(i=0;i4) + { + a=0; + x=INV_DESC_X; + y+=X_SKIP_Y; + } + } + } +*/ +/* +static void display_race_line(int line,char pushed) + { + int x,y; + char *c; + + set_font(H_FBOLD,pushed?0x3e0:0x7fff); + x=INV_DESK+137;y=INV_DESC_Y+170+22*line; + put_textured_bar(ablock(H_BUTBIG),x,y,100,20,0,20*pushed); + x+=49+pushed;y+=9+pushed; + if (cur_xicht==-1 || !women[cur_xicht]) c=texty[line+110];else c=texty[line+115]; + set_aligned_position(x,y,1,1,c);outtext(c); + } +*/ + +static void tlac2(int x,int y,char *text,int pushed) + { + set_font(H_FBOLD,pushed?0x3e0:0x7fff); + put_textured_bar(ablock(H_BUTSMALL),x,y,56,20,0,20*pushed); + x+=27+pushed;y+=9+pushed; + set_aligned_position(x,y,1,1,text);outtext(text); + } + +static tlac2_press(int x,int y,char *text) + { + schovej_mysku(); + tlac2(x,y,text,1); + ukaz_mysku(); + showview(x,y,56,20); + } + +/* +static void display_page2() + { + int i,x,y; + char s[10]; + + set_font(H_FBOLD,0x7fff); + position(INV_DESC_X,INV_DESC_Y);outtext(texty[122]); + x=INV_DESC_X+10;y=INV_DESC_Y+100; + for(i=0;i<4;i++) + { + position(x,y);outtext(texty[i+10]); + sprintf(s,"%d",postavy[cur_edited].stare_vls[i+VLS_SILA]); + set_aligned_position(x+140,y,2,0,s);outtext(s); + tlac2(x+150,y-5,"-",0); + tlac2(x+210,y-5,"+",0); + y+=30; + } + position(x,y);outtext(texty[19]); + sprintf(s,"%d",postavy[cur_edited].bonus); + set_aligned_position(x+140,y,2,0,s);outtext(s); + } +*/ +static void zobraz_staty(T_STATY *st) + { + char s[100]; + + set_font(H_FONT6,(28*1024+16*32+2)); + sprintf(s,texty[2],st->zivl,st->zivh); + position(250,3);outtext(s); + sprintf(s,texty[3],st->manl,st->manh); + position(350,3);outtext(s); + sprintf(s,texty[4],st->konl,st->konh); + position(450,3);outtext(s); + sprintf(s,texty[5],st->akc); + position(550,3);outtext(s); + } + +void redraw_generator() + { + T_STATY z; + memset(&z,20,sizeof(z)); + schovej_mysku(); + put_picture(INV_DESK,SCREEN_OFFLINE,ablock(H_GENERACE)); + put_picture(0,SCREEN_OFFLINE,ablock(H_IOBLOUK)); + bott_draw(1); + memcpy(screen+(480-102)*640,ablock(H_BOTTBAR),640*102*2); + put_picture(0,0,ablock(H_GEN_TOPBAR)); + zobraz_staty(&z); + ukaz_mysku(); + showview(0,0,0,0); + } + +static char page1_xicht(int id,int xa,int ya,int xr,int yr) + { + THUMAN *p; + char s[15]; + xa,ya,id; + if (xr%X_SKIP_X>54 || yr%X_SKIP_Y>75) return 0; + xr/=X_SKIP_X; + yr/=X_SKIP_Y; + cur_xicht=yr*5+xr; + sprintf(s,CHAR_NAME,cur_xicht); + def_handle(H_CHARS+cur_edited,s,pcx_fade_decomp,SR_BGRAFIKA); + sprintf(s,XICHT_NAME,cur_xicht); + def_handle(H_XICHTY+cur_edited,s,pcx_8bit_decomp,SR_BGRAFIKA); + p=postavy+cur_edited; + p->used=1; + p->lives=1; + p->xicht=cur_xicht; + p->sektor=viewsector; + prepocitat_postavu(p); + redraw_generator(); + return 1; + } + +static char page1_tlac1(int id,int xa,int ya,int xr,int yr) + { + yr/=22;yr,xa,ya,id,xr; + if (yrvlastnosti; + //common definiton + p->used=1; + p->groupnum=1; + p->sipy=0; + p->inv_size=6; + p->level=1; + p->exp=rnd(200); + p->female=women[p->xicht]; + switch(povolani) + { + case 0:w[VLS_SILA]=5+rnd(5); + w[VLS_SMAGIE]=0; + w[VLS_POHYB]=rnd(7)+2; + w[VLS_OBRAT]=rnd(5)+1; + w[VLS_MAXHIT]=10+rnd(10); + w[VLS_MAXMANA]=0; + w[VLS_KONDIC]=rnd(10)+10; + w[VLS_HPREG]=2; + w[VLS_MPREG]=1; + w[VLS_VPREG]=1; + p->bonus_zbrani[TPW_MEC]=1; + p->bonus_zbrani[TPW_SEKERA]=1; + break; + case 1:w[VLS_SILA]=rnd(5)+3; + w[VLS_SMAGIE]=rnd(5); + w[VLS_POHYB]=rnd(7)+2; + w[VLS_OBRAT]=rnd(7)+1; + w[VLS_MAXHIT]=10+rnd(10); + w[VLS_MAXMANA]=rnd(10); + w[VLS_KONDIC]=rnd(10)+10; + w[VLS_HPREG]=1; + w[VLS_MPREG]=1; + w[VLS_VPREG]=2; + p->bonus_zbrani[TPW_MEC]=1; + p->bonus_zbrani[TPW_DYKA]=1; + break; + case 2:w[VLS_SILA]=rnd(4)+1; + w[VLS_SMAGIE]=rnd(5)+5; + w[VLS_POHYB]=rnd(4)+1; + w[VLS_OBRAT]=rnd(4)+1; + w[VLS_MAXHIT]=5+rnd(5); + w[VLS_MAXMANA]=5+rnd(10); + w[VLS_KONDIC]=rnd(5)+10; + w[VLS_HPREG]=1; + w[VLS_MPREG]=2; + w[VLS_VPREG]=1; + p->bonus_zbrani[TPW_HUL]=1; + p->bonus_zbrani[TPW_DYKA]=1; + break; + case 3:w[VLS_SILA]=rnd(4)+1; + w[VLS_SMAGIE]=0; + w[VLS_POHYB]=rnd(5)+4; + w[VLS_OBRAT]=rnd(5)+5; + w[VLS_MAXHIT]=10+rnd(5); + w[VLS_MAXMANA]=0; + w[VLS_KONDIC]=rnd(5)+10; + w[VLS_HPREG]=1; + w[VLS_MPREG]=1; + w[VLS_VPREG]=1; + p->bonus_zbrani[TPW_STRELNA]=3; + break; + case 4:w[VLS_SILA]=rnd(4)+1; + w[VLS_SMAGIE]=0; + w[VLS_POHYB]=rnd(7)+2; + w[VLS_OBRAT]=rnd(4)+6; + w[VLS_MAXHIT]=5+rnd(5); + w[VLS_MAXMANA]=5+rnd(10); + w[VLS_KONDIC]=rnd(5)+10; + w[VLS_HPREG]=1; + w[VLS_MPREG]=1; + w[VLS_VPREG]=1; + p->bonus_zbrani[TPW_DYKA]=3; + break; + } + p->lives=w[VLS_MAXHIT]; + p->mana=w[VLS_MAXMANA]; + p->kondice=w[VLS_KONDIC]; + p->jidlo=MAX_HLAD(p); + p->voda=MAX_ZIZEN(p); + memcpy(p->stare_vls,p->vlastnosti,sizeof(p->vlastnosti)); + } + +static char page1_tlac2(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + tlac2_press(INV_DESK+290,340,texty[120]); + timered_redraw(); + if (cur_xicht==-1 || loc_select==-1) return 1; + cur_page=2; + generate_vlastnosti(postavy+cur_edited,loc_select); + return 1; + } + + +void enter_generator() + { + int i; + + curcolor=0;bar(0,0,639,479); + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#include "engine1.h" + +#define get_shift_state() ((GetKeyState(VK_SHIFT) & 0x80)!=0) +int default_ms_cursor=0; + +char spell_cast=0; + +char clk_step(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr; + spell_cast=0; + pick_set_cursor(); + switch (id) + { + case H_SIPKY_S:step_zoom(0);break; + case H_SIPKY_J:step_zoom(2);break; + case H_SIPKY_SV:turn_zoom(1);break; + case H_SIPKY_SZ:turn_zoom(-1);break; + case H_SIPKY_Z:step_zoom(3);break; + case H_SIPKY_V:step_zoom(1);break; + default:return 0; + } + return 1; + } + +char clk_touch_vyk(int sector,int side,int xr,int yr) + { + int i; + TVYKLENEK *v; + int x1,y1,x2,y2; + + if (picked_item!=NULL && picked_item[1]!=0) return 0; + for(i=0;v=map_vyk+i,isector==sector && v->dir==side) break; + if (i==vyk_max) return 0; + x1=v->xpos-v->xs/2; + x2=v->xpos+v->xs/2; + y1=320-(v->ypos+v->ys); + y2=320-(v->ypos); + x1+=MIDDLE_X-points[0][1][1].x; + x2+=MIDDLE_X-points[0][1][1].x; + y1+=MIDDLE_Y+points[0][1][1].y; + y2+=MIDDLE_Y+points[0][1][1].y; + if (x1<=xr && xr<=x2 && y1<=yr && yr<=y2) + { + if (picked_item==NULL) + { + for(i=0;v->items[i];i++);if (!i) return 0; + i--; + picked_item=NewArr(short,2); + picked_item[0]=v->items[i];picked_item[1]=0; + v->items[i]=0; + do_items_specs(); + pick_set_cursor(); + call_macro(viewsector*4+viewdir,MC_VYKEVENT); + return 1; + } + else + { + int fc; + word *w; + for(i=0;v->items[i];i++);if (i==8) + { + bott_disp_text(texty[36]); + return 1; + } + fc=picked_item[0];fc=glob_items[fc-1].vzhled+face_arr[0]; + w=ablock(fc); + if (v->xsysitems[i]=picked_item[0]; + v->items[i+1]=0; + call_macro(viewsector*4+viewdir,MC_VYKEVENT); + free(picked_item);picked_item=NULL; + pick_set_cursor(); + return 1; + } + } + return 0; + } + +char clk_touch(int id,int xa,int ya,int xr,int yr) + { + int x1,y1,x2,y2; + word *p; + int ext=0; + + xa;ya;id; + spell_cast=0; + pick_set_cursor(); + id=viewsector*4+viewdir; + if (map_sides[id].oblouk & 0x10) if (clk_touch_vyk(viewsector,viewdir,xr,yr))return 1; + if (map_sides[id].flags & SD_SEC_VIS && map_sides[id].sec!=0) + { + xa=map_sides[id].xsec<<1; + ya=320-(map_sides[id].ysec<<1); + p=(word *)ablock(map_sides[id].sec+num_ofsets[MAIN_NUM]); + x1=*p++;y1=*p++; + x2=xa+x1/2;y2=ya+y1/2;y1=y2-y1;x1=x2-x1; + x1+=MIDDLE_X-points[0][1][1].x; + x2+=MIDDLE_X-points[0][1][1].x; + y1+=MIDDLE_Y+points[0][1][1].y; + y2+=MIDDLE_Y+points[0][1][1].y; + ext=1; + } + else if (map_sides[id].sec==0) + { + x1=MIDDLE_X-points[0][0][1].x; + y1=MIDDLE_Y+points[0][1][1].y; + x2=640-x1; + y2=MIDDLE_Y+points[0][0][1].y; + ext=((map_sides[id].flags & SD_THING_IMPS) && !(map_sides[id].oblouk & SD_ITPUSH)); + } + if (x1<=xr && xr<=x2 && y1<=yr && yr<=y2) + { + a_touch(viewsector,viewdir); + return ext; + } + return 0; + } + +char clk_fly_cursor(int id,int xa,int ya,int xr,int yr) + { + id; + + if (spell_cast) + { + spell_cast=0; + pick_set_cursor(); + return 1; + } + if (yr>180) + if(xr>480) clk_step(H_SIPKY_V,xa,ya,xr,yr); + else if(xr<160) clk_step(H_SIPKY_Z,xa,ya,xr,yr); + else clk_step(H_SIPKY_J,xa,ya,xr,yr); + else + if(xr>480) clk_step(H_SIPKY_SV,xa,ya,xr,yr); + else if(xr<160) clk_step(H_SIPKY_SZ,xa,ya,xr,yr); + else clk_step(H_SIPKY_S,xa,ya,xr,yr); + return 1; + } + +char clk_throw(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya; + if (picked_item!=NULL) + { + throw_fly(xr,yr,0); + return 1; + } + return 0; + } + +char go_map(int id,int xa,int ya,int xr,int yr) + { + int i=15*256; + id;xa;ya;xr;yr; + + if (cur_mode==MD_ANOTHER_MAP) + {unwire_proc();wire_proc();return 1;} + spell_cast=0; + pick_set_cursor(); + send_message(E_KEYBOARD,i); + return 1; + } + +char go_book(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + + if (cur_mode==MD_ANOTHER_MAP) unwire_proc(),wire_proc(); + spell_cast=0; + pick_set_cursor(); + wire_kniha(); + return 1; + } + + +char konec(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + unwire_proc(); + if (!message(2,0,1,texty[118],texty[76],texty[77],texty[78])) + { + if (cur_mode==MD_ANOTHER_MAP) unwire_proc(),wire_proc(); + send_message(E_CLOSE_MAP); + } + else wire_proc(); + return 1; + } + +char spell_casting(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + if (picked_item!=NULL) return 1; + spell_cast=1; + mouse_set_default(H_MS_WHO); + return 1; + } + + +char clk_sleep(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + if (cur_mode==MD_ANOTHER_MAP) unwire_proc(),wire_proc(); + if (mglob.map_effector==ME_MESTO) + { + bott_disp_text(texty[120]); + return 1; + } + if (!battle) add_task(8100,sleep_players); + return 1; + } + + +char start_invetory(int id,int xa,int ya,int xr,int yr) + { + THUMAN *p; + int i; + word *xs; + + id;xa;ya;yr; + if (cur_mode==MD_ANOTHER_MAP) unwire_proc(),wire_proc(); + if (bott_display!=BOTT_NORMAL) + { + schovej_mysku(); + bott_draw(1); + other_draw(); + ukaz_mysku(); + showview(0,376,640,104); + return 1; + } + xs=ablock(H_OKNO); + i=xr/xs[0]; + if (iused) + { + if (ms_last_event.event_type & 0x2) + { + if (GetKeyState(VK_CONTROL) & 0x80) + { + if (p->sektor==viewsector) + { + add_to_group(i); + zmen_skupinu(p); + return 1; + } + return 1; + } + if (select_player!=i && select_player!=-1 && picked_item==NULL && !(cur_mode==MD_INV && battle_mode==MD_PREZBROJIT)) + { + select_player=i; + zmen_skupinu(p); + bott_draw(1); + if (cur_mode==MD_INBATTLE) return 1; + } + if (p->groupnum!=cur_group || spell_cast) + { + if (picked_item!=NULL && p->sektor!=viewsector) return 0; + if (spell_cast && p->sektor==viewsector) + { + wire_fly_casting(i); + spell_cast=0; + mouse_set_default(H_MS_DEFAULT); + return 1; + } + zmen_skupinu(p); + if (cur_mode==MD_GAME && p->groupnum) return 1; + } + if (!p->groupnum && p->sektor!=viewsector) return 1; + unwire_proc(); + wire_inv_mode(p); + return 0; + } + else + { + if (picked_item==NULL) return 0; + if (p->sektor==viewsector) + if (put_item_to_inv(p,picked_item)) + { + free(picked_item); + picked_item=NULL; + } + pick_set_cursor(); + if (cur_mode==MD_INV) + { + unwire_proc(); + wire_inv_mode(human_selected); + } + return 1; + } + } + } + return 0; + } + +char clk_group_all(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + unwire_proc(); + wire_proc(); + group_all(); + return 1; + } + +char clk_saveload(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr; + if (id && battle) + { + bott_disp_text(texty[81]);other_draw();showview(0,0,0,0); + return 1; + } + if (id && !GlobEvent(MAGLOB_CLICKSAVE,viewsector,viewdir)) + return 1; + if (cur_mode==MD_ANOTHER_MAP) unwire_proc(),wire_proc(); + unwire_proc(); + cancel_render=1; + wire_save_load(id); + return 1; + } + +char return_game(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + if (ms_last_event.event_type & 0x8) + { + unwire_proc(); + wire_proc(); + } + return 0; + } + +char clk_mob_alter(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + + xa=viewsector; + id=mob_map[xa]; + while (id==0 || mobs[id-1].dialog==-1) + { + if (id) id=mobs[id-1].next; + if (id==0 && xa==viewsector) + if (~map_sides[(xa<<2)+viewdir].flags & SD_PLAY_IMPS) + { + xa=map_sectors[xa].step_next[viewdir]; + id=mob_map[xa]; + } + else return 0; + else return 0; + } + id--; + start_dialog(mobs[id].dialog,id); + return 1; + } + +char empty_clk(int id,int xa,int ya,int xr,int yr) //tato udalost slouzi ke zruseni nekterych mist v globalni mape + { + id,xa,ya,xr,yr; + return 1; + } + +static char sing_song_clk(int id,int xa,int ya,int xr,int yr) + { + char *xadr; + word *xs; + static char playing=0; + char standardflute=map_sectors[viewsector].sector_type>=S_FLT_SMER && + map_sectors[viewsector].sector_type12 || (ms_last_event.event_type & 0x4)) + { + if (playing) + { + THE_TIMER *t; + stop_play_flute(); + playing=0; + if (standardflute) + { + if (fletna_get_buffer_pos()) + { + THE_TIMER *t; + if (standardflute) + { + t=add_to_timer(TM_FLETNA,100,1,check_fletna); + t->userdata[0]=viewsector; + t->userdata[1]=viewdir; + } + } + } + else + { + t=add_to_timer(TM_FLETNA,100,1,check_global_fletna); + t->userdata[0]=viewsector; + t->userdata[1]=viewdir; + } + + } + return id<12; + } + if (~ms_last_event.event_type & 0x2) return 1; + start_play_flute(id); + playing=1; + if (standardflute) + { + fletna_pridej_notu(id); + delete_from_timer(TM_FLETNA); + } + else + { + fletna_glob_add_note(id); + delete_from_timer(TM_FLETNA); + } + return 1; + } + + +T_CLK_MAP clk_main_view[]= + { + {H_SIPKY_S,561,378,598,407,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_SZ,530,387,560,418,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_Z,529,419,555,453,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_J,560,446,598,474,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_SV,599,387,628,418,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_V,605,420,632,454,clk_step,2,H_MS_DEFAULT}, + {MS_GAME_WIN,0,17,639,377,clk_fly_cursor,8,-1}, + {1,320,303,639,376,pick_item_,2,-1},//344 + {0,0,303,320,376,pick_item_,2,-1},//344 + {3,0,200,320,340,pick_item_,2,-1},//303 + {2,320,200,639,340,pick_item_,2,-1},//303 + {MS_GAME_WIN,0,17,639,377,clk_touch,2,-1}, + {MS_GAME_WIN,0,17,639,377,clk_throw,2,-1}, + {MS_GAME_WIN,0,17,639,250,clk_mob_alter,2,-1}, + {-1,0,378,639,479,sing_song_clk,0xff,-1}, + {-1,54,378,497,479,start_invetory,2+8,-1}, + {-1,315,0,335,14,spell_casting,2,-1}, + }; + +#define GAME_CLK_MAP 8 +T_CLK_MAP game_clk_map[]= + { + {-1,499,379,518,390,clk_group_all,2,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,291,0,313,14,go_book,2,H_MS_DEFAULT}, + {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {1,147,0,205,14,clk_saveload,2,H_MS_DEFAULT}, + {0,207,0,265,14,clk_saveload,2,H_MS_DEFAULT}, + {-1,267,0,289,15,clk_sleep,2,H_MS_DEFAULT}, + }; + + +T_CLK_MAP *click_map=NULL; +int click_map_size=0; +T_CLK_MAP *global_click_map=NULL; +int global_click_map_size=0; + +int find_in_click_map(MS_EVENT *ms,T_CLK_MAP *pt,int pocet,int *evtype) + { + int mscur=-1; + while (pocet--) + { + if (ms->x>=pt->xlu && ms->x<=pt->xrb && ms->y>=pt->ylu && ms->y<=pt->yrb) + { + if (mscur==-1) mscur=pt->cursor; + if ((*evtype) & pt->mask) + if (pt->proc!=NULL) + if (pt->proc(pt->id,ms->x,ms->y,ms->x-pt->xlu,ms->y-pt->ylu)) + { + evtype[0]&=~pt->mask; + if (!evtype[0]) break; + } + } + pt++; + } + return mscur; + } + + +void ms_clicker(EVENT_MSG *msg,void **usr) + { + MS_EVENT *ms; + + usr; + if (pass_zavora) return; + switch (msg->msg) + { + case E_INIT:return; + case E_DONE:return; + case E_MOUSE: + { + int mscur; + int msc=-1; + int evtype; + ms=get_mouse(msg); + mscur=-1; + evtype=ms->event_type; + mscur=find_in_click_map(ms,click_map,click_map_size,&evtype); + if (evtype) msc=find_in_click_map(ms,global_click_map,global_click_map_size,&evtype); + if (mscur==-1) mscur=msc; + if (mscur!=-1) mouse_set_cursor(mscur); + else mouse_set_cursor(default_ms_cursor); + } + break; + } + return; + } + +void change_click_map(T_CLK_MAP *map,int mapsize) + { + click_map=map; + click_map_size=mapsize; + } + +void save_click_map(void **map,int *mapsize) + { + *map=click_map; + *mapsize=click_map_size; + } + +void restore_click_map(void *map,int mapsize) + { + click_map=(T_CLK_MAP *)map; + click_map_size=mapsize; + } + + + +void change_global_click_map(T_CLK_MAP *map,int mapsize) + { + global_click_map=map; + global_click_map_size=mapsize; + } + +void set_game_click_map(void) + { + change_global_click_map(game_clk_map,GAME_CLK_MAP); + } + + +T_CLK_MAP map_disabled= + {-1,0,0,639,479,empty_clk,0xff,-1}; + +void disable_click_map(void) + { + change_click_map(&map_disabled,1); + } diff --git a/GAME/CRC.C b/GAME/CRC.C new file mode 100644 index 0000000..7cc267e --- /dev/null +++ b/GAME/CRC.C @@ -0,0 +1,31 @@ +#include +#include + +unsigned long l; + +#define ZAKLAD_CRC 0xC005 + +char data[100000]; +long delka; +FILE *f; + + +main() + { + int i; + f=fopen("CRC.C","rb"); + memset(data,0,sizeof(data)); + delka=fread(data,1,sizeof(data),f); + fclose(f); + memcpy(&l,data,2);i=0; + l%=ZAKLAD_CRC; + while(i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" + +typedef struct t_paragraph + { + unsigned num:15; + unsigned alt:15; + unsigned visited:1; + unsigned first:1; + long position; + }T_PARAGRAPH; + +#define STR_BUFF_SIZ 4096 +#define SAVE_POSTS 20 +#define P_STRING 1 +#define P_SHORT 2 +#define P_VAR 3 + +#define MAX_VOLEB 10 + +#define VOLBY_X 85 +#define VOLBY_Y 398 +#define VOLBY_XS 450 +#define VOLBY_YS 10 + +#define TEXT_X 17 +#define TEXT_Y 270 +#define TEXT_XS 606 +#define TEXT_YS 94 +#define TEXT_STEP 11 + +#define OPER_EQ 32 +#define OPER_BIG 35 +#define OPER_LOW 33 +#define OPER_BIGEQ 36 +#define OPER_LOWEQ 34 +#define OPER_NOEQ 37 + +#define PIC_X 17 +#define PIC_Y (17+SCREEN_OFFLINE) + +#define DESC_COLOR1 (RGB555(28,28,21)) + +static short varibles[20]; + +static char sn_nums[SAVE_POSTS]; +static char sn_nams[SAVE_POSTS][32]; +static char sn_rods[SAVE_POSTS]; + +static word *back_pic; +static char back_pic_enable=0; + +static char showed=0; +static char *pc; +static char *descript=NULL; +static char *string_buffer=NULL; +static char iff; + +static char _flag_map[32]; + +static int local_pgf=0; + +static char story_on=0; + +static char pocet_voleb=0; +static char vyb_volba=0; +static short vol_n[MAX_VOLEB]; +//static char *vol_s[MAX_VOLEB]; +static short save_jump; + +static TSTR_LIST history=NULL; +static int his_line=0; +static int end_text_line=0; +static int last_his_line=0; + +static int starting_shop=-1; + +static char halt_flag=0; + +static int dialog_mob=0; + +static char code_page=1; + +static char case_click(int id,int xa,int ya,int xr,int yr); +static char ask_who_proc(int id,int xa,int ya,int xr,int yr); + + +#define CLK_DIALOG 3 +static T_CLK_MAP clk_dialog[CLK_DIALOG]= + { + {0,TEXT_X,TEXT_Y,TEXT_X+TEXT_XS,TEXT_Y+TEXT_YS,case_click,3,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {0,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + +#define CLK_DLG_WHO 3 +static T_CLK_MAP clk_dlg_who[CLK_DLG_WHO]= + { + {1,54,378,497,479,ask_who_proc,2,-1}, + {2,0,0,639,479,ask_who_proc,8,-1}, + {-1,0,0,639,479,empty_clk,0xff,-1}, + }; + + +static int glob_y; + +static int last_pgf; + +static word *paleta; +static long loc_anim_render_buffer; +static short task_num=-1; + +void small_anm_buff(void *target,void *buff,void *paleta); +//#pragma aux small_anm_buff parm[edi][esi][ebx] modify [eax ecx] +void small_anm_delta(void *target,void *buff,void *paleta); +//#pragma aux small_anm_delta parm[edi][esi][ebx] modify [eax ecx] + +static void animace_kouzla(int act,void *data,int csize) + { + word *p=GetScreenAdr()+loc_anim_render_buffer; + switch (act) + { + case MGIF_LZW: + case MGIF_COPY:small_anm_buff(p,data,paleta);break; + case MGIF_DELTA:small_anm_delta(p,data,paleta);break; + case MGIF_PAL:paleta=data;break; + } + } + + +static void dialog_anim(va_list args) +//#pragma aux dialog_anim parm [] + { + char *block=va_arg(args,char *); + int speed=va_arg(args,int); + int rep=va_arg(args,int); + + void *anm; + void *aptr; + char *ch; + char hid; + int spdc=0,cntr=rep,tm,tm2; + + loc_anim_render_buffer=PIC_Y*scr_linelen2+PIC_X; + mgif_install_proc(animace_kouzla); + concat(ch,pathtable[SR_DIALOGS],block); + free(block); + aptr=load_file(ch); + do + { + anm=open_mgif(aptr); + while (anm!=NULL && task_quitmsg()) + { + task_sleep(NULL); + if (!spdc) + { + if (ms_last_event.x<=PIC_X+320 && ms_last_event.y<=PIC_Y+180) + { + hid=1;schovej_mysku(); + } + else hid=0; + anm=mgif_play(anm); + spdc=speed; + if (hid) ukaz_mysku(); + showview(PIC_X,PIC_Y,320,180); + } + tm2=get_timer_value(); + if (tm!=tm2) + { + spdc--;tm=tm2; + } + } + rep--; + close_mgif(); + } + while (!cntr && rep && !task_quitmsg()); + free(aptr); + } + +static void stop_anim() + { + if (task_num!=-1) term_task(task_num); + } + +static void run_anim(char *name,int speed,int rep) + { + char *bl; + stop_anim(); + bl=getmem(strlen(name)+1);strcpy(bl,name); + task_num=add_task(8196,dialog_anim,bl,speed,rep); + } + +static void error(char *text) + { + char buff[256]; + sprintf(buff,"%s v odstavci %d\r\nLocal_pgf=%d / DIALOG : %d / SENTENCE : %d\r\n",text,last_pgf+local_pgf,local_pgf,local_pgf/128,last_pgf); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONSTOP|MB_SYSTEMMODAL); + SEND_LOG("(DIALOGS) Dialog error detected at %d:%d",local_pgf/128,last_pgf); + SEND_LOG("(DIALOGS) Error description: %s",text,0); + } + +static void show_dialog_picture() + { + if (!showed) + { + put_picture(0,SCREEN_OFFLINE,ablock(H_DIALOG)); + showed=1; + glob_y=250; + } + } + +static T_PARAGRAPH *find_paragraph(int num) + { + int *pp; + int pocet,i; + T_PARAGRAPH *z; + + num+=local_pgf; + pp=(int *)ablock(H_DIALOGY_DAT); + pocet=*pp;pp+=2; + z=(T_PARAGRAPH *)pp; + for(i=0;inum==(unsigned)num) return z; + { + char s[80]; + + sprintf(s,"Odstavec %d neexistuje! Odkaz byl vyvol n",num); + error(s); + return (T_PARAGRAPH *)pp; + } + } + +static int find_pgnum(char *pc) + { + T_PARAGRAPH *z; + int *pp; + int lastnum=-1; + int pocet; + int pcc,i; + + pp=(int *)ablock(H_DIALOGY_DAT); + pocet=*pp;pp+=2; + pcc=pc-(char *)pp-8-sizeof(T_PARAGRAPH)*pocet; + z=(T_PARAGRAPH *)pp; + for(i=0;iposition>pcc) break;else lastnum=z->num; + return lastnum-local_pgf; + } + +static void goto_paragraph(int prgf) + { + T_PARAGRAPH *z; + + + do + { + z=find_paragraph(prgf); + if (z->visited) z->first=1; + if (z->alt==z->num || !z->visited) + { + pc=((char *)ablock(H_DIALOGY_DAT))+*((int *)ablock(H_DIALOGY_DAT))*sizeof(T_PARAGRAPH)+8+z->position; + last_pgf=prgf; + z->visited=1; + return; + } + prgf=z->alt-local_pgf; + do_events(); + } + while (1); + } + +static char *transfer_text(char *source,char *target) + { + char *orgn=source,*ot=target; + int num; + while (*source) + { + if (*source=='%') + { + source++; + switch(*source) + { + case '[':*target++='[';break; + case ']':*target++=']';break; + case 'a':*target++='\'';break; + case 'p': + case '%':*target++='%';break; + case 'n':strcpy(target,sn_nams[0]);target+=strlen(sn_nams[0]);break; + default: num=0;while (isdigit(*source)) num=10*num+*source++-'0'; + if (*source=='l') + { + sn_nums[0]=sn_nums[num]; + strcpy(sn_nams[0],sn_nams[num]); + sn_rods[0]=sn_rods[num]; + } + break; + } + source++; + } + else if (*source=='[') + { + source++; + num=sn_rods[0]; + while(num>0) + { + source=strchr(source,','); + num--; + if (source==NULL) + { + char buff[256]; + closemode(); + sprintf(buff,"%s\r\nChybny rod nebo maly pocet tvaru od jednoho slova",orgn); + error(buff); + exit(-1); + } + source++; + } + while (*source!=',' && *source!=']' && *source!=0) *target++=*source++; + if (*source!=']') + { + source=strchr(source,']'); + if (source==NULL) + { + char buff[256]; + closemode(); + sprintf(buff,"%s\r\nOcekava se ]",orgn); + error(buff); + exit(-1); + } + } + source++; + } + else *target++=*source++; + } + *target=0; + if (code_page==2) + prekodovat(ot); + return target; + } + +static char *conv_text(char *source) + { + if (string_buffer==NULL) string_buffer=getmem(STR_BUFF_SIZ); + return transfer_text(source,string_buffer); + } + +static char zjisti_typ() + { + return *pc; + } + +static char *Get_string() + { + char *c,i; + if (*pc==P_STRING) + { + pc++; + c=conv_text(pc); + do + { + pc+=strlen(pc)+1; + if ((i=zjisti_typ())==P_STRING) + { + pc++; + c=transfer_text(pc,c); + } + } + while(i==P_STRING); + return string_buffer; + } + if (zjisti_typ()==P_SHORT) + { + short i; + pc++; + i=*(short *)pc;pc+=2; + if (i<=0) c=conv_text(texty[abs(i)]);else c=conv_text(level_texts[i]); + return string_buffer; + } + error("O‡ek v  se ©etzec nebo index do tabulky ©etzc–"); + exit(0); + return NULL; + } + +static short Get_short() + { + short p; + if (*pc==P_SHORT) + { + pc++; + p=*(short *)pc; + pc+=2; + return p; + } + if (*pc==P_VAR) + { + pc++; + p=*(short *)pc; + pc+=2; + return varibles[p]; + } + error("O‡ek v  se ‡ˇslo"); + exit(0); + return 0; + } + +static void show_desc() + { + char *c=descript; + int y; + + showed=0; + show_dialog_picture(); + if (c==NULL) return; + y=34; + set_font(H_FBOLD,DESC_COLOR1); + while (*c) + { + position(382,y); + outtext(c);y+=text_height(c); + c=strchr(c,0)+1; + } + } + +static void add_desc(char *c) + { + int xs,ys; + if (story_on) write_story_text(c); + if (descript!=NULL) free(descript); + descript=(char *)getmem(strlen(c)+2); + set_font(H_FBOLD,RGB555(31,31,31)); + zalamovani(c,descript,225,&xs,&ys); + } + +static void show_emote(char *c) + { + int xs,ys; + char *a; + + if (story_on) write_story_text(c); + a=alloca(strlen(c)+2); + set_font(H_FBOLD,RGB555(31,31,31)); + zalamovani(c,a,TEXT_XS,&xs,&ys); + while (*a) + { + char z[100]="M"; + strcat(z,a); + end_text_line=str_add(&history,z)+1; + a=strchr(a,0)+1; + } + } + + +static void echo(char *c) + { + int xs,ys; + char *a; + + if (story_on) write_story_text(c); + a=alloca(strlen(c)+2); + set_font(H_FBOLD,RGB555(0,30,0)); + zalamovani(c,a,TEXT_XS,&xs,&ys); + while (*a) + { + char z[100]="E"; + strcat(z,a); + end_text_line=str_add(&history,z)+1; + a=strchr(a,0)+1; + } + } + +#define TEXT_UNSELECT *((word *)ablock(H_DIALOG)+3+254) +#define TEXT_SELECT *((word *)ablock(H_DIALOG)+3+255) + +static void redraw_text() + { + int y=TEXT_Y; + int ys=TEXT_YS; + int ls_cn,i; + + + put_textured_bar(ablock(H_DIALOG),TEXT_X,TEXT_Y,TEXT_XS,TEXT_YS,TEXT_X,TEXT_Y-SCREEN_OFFLINE); + //create_frame(TEXT_X,TEXT_Y,TEXT_XS,TEXT_YS,1); + ls_cn=str_count(history); + if (ls_cn<=his_line) return; + + for (i=his_line;i=omz && chk[i]==0) + { + if (l>=0) chk[l]|=4; + l=-2;iff=0; + } + else if (l!=-2 && chk[i]==0 && postavy[i].vlastnosti[vls]>=m) + { + if (l>=0) chk[l]|=4; + l=i;iff=1; + m=postavy[i].vlastnosti[vls]; + } + else chk[i]|=4; + m=0; + for(i=0;i0;i++) if (!chk[i]) l--; + i--; + sn_nums[0]=i; + strcpy(sn_nams[0],postavy[i].jmeno); + sn_rods[0]=postavy[i].female; + } + +static void pc_xicht(int xichtid) +{ + int i; + for (i=0;ivisited; + } + +static void set_nvisited(int prgf) + { + T_PARAGRAPH *z; + + z=find_paragraph(prgf); + z->visited=0; + z->first=0; + } + + +void q_flag(int flag) + { + iff=_flag_map[flag>>3] & (1<<(flag & 0x7)); + } + +static void set_flag(int flag) + { + q_flag(flag); + _flag_map[flag>>3]|=(1<<(flag & 0x7)); + } + +static void reset_flag(int flag) + { + q_flag(flag); + _flag_map[flag>>3]&=~(1<<(flag & 0x7)); + } + +void change_flag(int flag,char mode) + { + if (mode==0) reset_flag(flag); + else if (mode==1) set_flag(flag); + else _flag_map[flag>>3]^=(1<<(flag & 0x7)); + } + +char test_flag(int flag) + { + return (_flag_map[flag>>3] & (1<<(flag & 0x7)))!=0; + } + +static void first_visited(int prgf) + { + T_PARAGRAPH *z; + + z=find_paragraph(prgf); + iff=!z->first; + } + + + +void do_dialog(); +static void remove_all_cases(); + +static void dialog_cont() + { + save_jump=vol_n[vyb_volba]; + remove_all_cases(); + echo(" "); + his_line=get_last_his_line(); + if (halt_flag) goto_paragraph(save_jump); + schovej_mysku(); + do_dialog(); + } + + +static void key_check(EVENT_MSG *msg,void **unused) + { + char c,d; + + unused; + if (msg->msg==E_KEYBOARD) + { + c=*(char *)msg->data; + d=*(int *)msg->data>>8; + if (c==0) + { + switch(d) + { + case 'H':if (vyb_volba==0) his_line-=(his_line>0);else vyb_volba--;break; + case 'P':if (his_linemsg=-1; + } + else if (c==27) konec(0,0,0,0,0); + } + } + +void wire_dialog(); +void wire_dialog_drw() + { + schovej_mysku(); + wire_dialog(); + draw_all(); + ukaz_mysku(); + showview(0,0,0,0); + } +void unwire_dialog() + { + send_message(E_DONE,E_KEYBOARD,key_check); + disable_click_map(); +// wire_proc=wire_dialog_drw; + } + +void wire_dialog() + { + cancel_render=1; + send_message(E_ADD,E_KEYBOARD,key_check); + change_click_map(clk_dialog,CLK_DIALOG); + unwire_proc=unwire_dialog; + showview(0,0,0,0); + last_his_line=his_line; + } + + +short *q_item_one(int i,int itnum) + { + int j; + THUMAN *p=&postavy[i]; + for(j=0;jinv_size;j++) + if (p->inv[j]==itnum) return &p->inv[j]; + for(j=0;jwearing[j]==itnum) return &p->wearing[j]; + for(j=0;jprsteny[j]==itnum) return &p->wearing[j]; + return NULL; + } + +short *q_item(int itnum,int sector) + { + int i; + short *p; + + itnum++; + for(i=0;iMAX_VOLEB) {error("POZOR! Je priliz mnoho voleb");pocet_voleb=MAX_VOLEB;} + a=alloca(strlen(text)+2); + set_font(H_FBOLD,RGB555(0,30,0)); + zalamovani(text,a,TEXT_XS,&xs,&ys); + while (*a) + { + char z[100]; + z[0]=pocet_voleb+48; + z[1]=0; + strcat(z,a); + str_add(&history,z); + a=strchr(a,0)+1; + } + pocet_voleb++; + } + +static void remove_all_cases() + { + int cf,i; + pocet_voleb=0; + cf=str_count(history); + for(i=end_text_line;i1) + { + id=yr/TEXT_STEP; + cf=str_count(history); + id+=his_line; + if (id>=cf) return 0; + if (history[id]==NULL) return 0; + id=history[id][0]; + if (id=='E' || id=='M') return 0; + id-=48; + if (id!=vyb_volba) + { + vyb_volba=id; + schovej_mysku(); + redraw_text(); + ukaz_mysku(); + showview(TEXT_X,TEXT_Y,TEXT_XS,TEXT_YS); + } + if (ms_last_event.event_type & 0x2) + { + dialog_cont(); + } + } + else + if (ms_last_event.event_type & 0x2) + { + dialog_cont(); + } + return 1; + } + +void dialog_select(char halt) + { + showed=0; + unwire_proc(); + draw_all(); + ukaz_mysku(); + wire_dialog(); + halt_flag=halt && (pocet_voleb>0); + } + +void dialog_select_jump() + { + goto_paragraph(save_jump); + } + +static void exit_dialog() + { + _flag_map[0]|=0x1; + stop_anim(); + if (dialog_mob>-1) + { + mobs[dialog_mob].dialog_flags=_flag_map[0]; + mobs[dialog_mob].stay_strategy=_flag_map[1]; + } + unwire_proc(); + aunlock(H_DIALOGY_DAT); + ukaz_mysku(); + free(descript);descript=NULL; + free(string_buffer);string_buffer=NULL; + remove_all_cases(); + release_list(history); + history=0; + free(back_pic); + undef_handle(H_DIALOG_PIC); + if (starting_shop!=-1 && !battle) + { + enter_shop(starting_shop); + ukaz_mysku(); + update_mysky(); + cancel_pass=0; + } + else + { + wire_proc(); + norefresh=0; + } + starting_shop=-1; + SEND_LOG("(DIALOGS) Exiting dialog...",0,0); + } + + +static void picture(char *c) + { + undef_handle(H_DIALOG_PIC); + if (strcmp(c,"SCREEN")) def_handle(H_DIALOG_PIC,c,hi_8bit_correct,SR_DIALOGS),back_pic_enable=0; + else back_pic_enable=1; + } + + + +static void dlg_start_battle() + { + if (dialog_mob!=-1) + { + mobs[dialog_mob].vlajky|=MOB_IN_BATTLE; + } + battle=1; + } + +static void teleport_group(short sector,short dir) + { + int i; + THUMAN *h=postavy; + + destroy_player_map(); + for(h=postavy,i=0;iused && h->groupnum==cur_group) + { + recheck_button(h->sektor,1); + recheck_button(sector,1); + h->sektor=sector; + h->direction=dir; + } + viewsector=sector; + viewdir=dir; + build_player_map(); + } + +extern THUMAN postavy_2[]; + +char join_character(int i) + { + THUMAN *h; + THUMAN *s=postavy_2+i; + int j; + + SEND_LOG("(DIALOGS) Joining character '%s'",s->jmeno,0); + for(j=0,h=postavy;jused) + { + memcpy(h,s,sizeof(THUMAN)); + h->sektor=viewsector; + h->direction=viewdir; + h->groupnum=cur_group; + reg_grafiku_postav(); + bott_draw(1); + return 0; + } + SEND_LOG("(DIALOGS) Join failed - no room for new character",0,0); + return 1; + } + + +static int selected_player; + +char drop_character() +{ + int selected_player=sn_nums[0]; + if (selected_player<0 || selected_player>=POCET_POSTAV) return 1; + memcpy(postavy+selected_player,postavy+selected_player+1,sizeof(*postavy)*(POCET_POSTAV-selected_player)); + postavy[POCET_POSTAV-1].used=0; + reg_grafiku_postav(); + bott_draw(1); + return 0; +} + + +static char dead_players=0; + +static char ask_who_proc(int id,int xa,int ya,int xr,int yr) + { + { + THUMAN *p; + int i; + word *xs; + + if (id==2) + { + selected_player=-1; + exit_wait=1; + return 1; + } + xs=ablock(H_OKNO); + i=xr/xs[0];yr;xa;ya;id; + if (iused && ((p->lives!=0) ^ (dead_players))) + if (p->sektor==viewsector) + { + selected_player=i; + exit_wait=1; + } + } + return 1; + } + + } + + +static dlg_ask_who() + { + draw_all(); + mouse_set_default(H_MS_WHO); + ukaz_mysku(); + showview(0,0,0,0); + *otevri_zavoru=1; + change_click_map(clk_dlg_who,CLK_DLG_WHO); + escape(); + dead_players=0; + schovej_mysku(); + mouse_set_default(H_MS_DEFAULT); + if (selected_player==-1) return 1; + strcpy(sn_nams[0],postavy[selected_player].jmeno); + sn_rods[0]=postavy[selected_player].female; + sn_nums[0]=selected_player; + change_click_map(NULL,0); + return 0; + } + +extern word weapon_skill[]; + +static void pract(h,vls,how,max) + { + iff=0; + if (vls>=100) + { + vls-=100; + if (postavy[h].bonus_zbrani[vls]>=max) iff=1; + else + { + postavy[h].bonus_zbrani[vls]+=how; + if (postavy[h].bonus_zbrani[vls]>max) postavy[h].bonus_zbrani[vls]=max,iff=1; + postavy[h].weapon_expy[vls]=weapon_skill[postavy[h].bonus_zbrani[vls]]; + } + } + else + { + if (postavy[h].vlastnosti[vls]>=max) iff=1; + else + { + postavy[h].stare_vls[vls]+=how; + prepocitat_postavu(postavy+h); + if (postavy[h].vlastnosti[vls]>max) + { + postavy[h].stare_vls[vls]-=postavy[h].vlastnosti[vls]-max; + postavy[h].vlastnosti[vls]=max; + iff=1; + } + } + } + } + +static void pract_to(h,vls,how) + { + iff=0; + if (vls>=100) + { + vls-=100; + if (postavy[h].bonus_zbrani[vls]val2; + case OPER_LOW:return val1=val2; + case OPER_LOWEQ:return val1<=val2; + case OPER_NOEQ:return val1!=val2; + default:error("Chybn operator porovn v nˇ"); + } + return 0; + } + +static char test_vls(h,vls,oper,num) + { + int val; + if (vls>=100) + { + vls-=100; + val=postavy[h].bonus_zbrani[vls]; + } + else + val=postavy[h].stare_vls[vls]; + return oper_balance(val,num,oper); + } + +static char atsector(int oper,int sector) + { + return oper_balance(viewsector,sector,oper); + } + + +static void dark_screen(int time,int gtime) + { + int z,i; + THUMAN *h; + i=get_timer_value()+time*50; + curcolor=0; + bar(0,17,639,377); + showview(0,0,0,0); + while (get_timer_value()used && h->lives) + { + z=h->vlastnosti[VLS_HPREG]*gtime;z+=h->lives; + if (z>h->vlastnosti[VLS_MAXHIT]) z=h->vlastnosti[VLS_MAXHIT];h->lives=z; + z=h->vlastnosti[VLS_MPREG]*gtime;z+=h->mana; + if (z>h->vlastnosti[VLS_MAXMANA]) z=h->vlastnosti[VLS_MAXMANA];h->mana=z; + z=h->vlastnosti[VLS_VPREG]*gtime;z+=h->kondice; + if (z>h->vlastnosti[VLS_KONDIC]) z=h->vlastnosti[VLS_KONDIC];h->kondice=z; + } + bott_draw(0); + } + +static char najist_postavy(int cena) + { + int i,s=0; + THUMAN *h=postavy; + + for(i=0;iused && h->sektor==viewsector && h->lives) s=s+cena; + if (s>money) return 1; + money-=s; + for(i=0,h=postavy;iused && h->sektor==viewsector && h->lives) + { + h->jidlo=MAX_HLAD(h); + h->voda=MAX_ZIZEN(h); + } + return 0; + } + +static char isall() + { + THUMAN *h=postavy; + int i; + + for(i=0,h=postavy;isektor!=viewsector && h->used && h->lives) return 0; + return 1; + } + +static void spat(int hodin) + { + sleep_ticks=hodin*HODINA;add_task(16384,sleep_players); + insleep=1; + while (insleep) do_events(); + } + +static char test_volby_select(int balance,int value) + { + return oper_balance(pocet_voleb,value,balance); + } + +static void cast_spell(int spell) + { + int cil=1+sn_nums[0]; + + add_spell(spell,cil,cil,1); + } + + +void do_dialog() + { + int i,p1,p2,p3; + char *c; + + do + { + i=Get_short();p3=0; + switch(i) + { + case 128:add_desc(Get_string());break; + case 129:show_emote(Get_string());break; + case 130:save_name(Get_short());break; + case 131:iff=!iff; + case 132:load_name(Get_short());break; + case 133:nahodne(0,0,Get_short());break; + case 134:p1=Get_short();p2=Get_short();nahodne(VLS_SMAGIE,p1,p2);break; + case 135:p1=Get_short();p2=Get_short();nahodne(VLS_SILA,p1,p2);break; + case 136:p1=Get_short();p2=Get_short();nahodne(VLS_OBRAT,p1,p2);break; + case 137:c=Get_string();p1=Get_short();strncpy(sn_nams[0],c,32);sn_rods[0]=p1;break; + case 138:iff=Get_short();break; + case 139:goto_paragraph(Get_short());break; + case 140:p1=Get_short();if (iff) goto_paragraph(p1);break; + case 141:p1=Get_short();if (!iff) goto_paragraph(p1);break; + case 142:p1=Get_short();add_case(p1,Get_string());break; + case 143:p1=Get_short();p2=Get_short();c=Get_string();if (iff==p1) add_case(p2,c);break; + case 144:dialog_select(1);return; + case 145:iff=visited(Get_short());break; + case 146:p1=Get_short();c=Get_string();iff=visited(p1);if (iff==0) add_case(p1,c);break; + case 147:picture(Get_string());break; + case 148:echo(Get_string());break; + case 149:cur_page=count_pages(); + cur_page&=~0x1; + cur_page++; + add_to_book(Get_short()); + play_fx_at(FX_BOOK); + if (game_extras & EX_AUTOOPENBOOK) autoopenaction=1; + break; + case 150:set_nvisited(Get_short());break; + case 151:iff=rnd(100)<=Get_short();break; + case 152:iff=q_item(Get_short(),viewsector)!=NULL;break; + case 153:create_item(Get_short());break; + case 154:destroy_item(Get_short());break; + case 155:money+=Get_short();break; + case 156:p1=Get_short();if (p1>money) iff=1;else money-=p1;break; + case 157:dlg_start_battle();break; + case 158:p1=Get_short();p2=Get_short();delay_action(0,p1,p2,0,0,0);break; + case 160:p1=Get_short();p2=Get_short();teleport_group(p1,p2);break; + case 161:c=Get_string();p1=Get_short();p2=Get_short();run_anim(c,p1,p2);break; + case 162:lecho(Get_string());break; + case 163:q_flag(Get_short());break; + case 164:dialog_select(0);return; + case 165:dialog_select_jump();break; + case 166:first_visited(Get_short());break; + case 167:local_pgf=Get_short();break; + case 168:starting_shop=Get_short();break; + case 169:p1=Get_short();if (!iff) pc+=p1;break; + case 170:p1=Get_short();if (iff) pc+=p1;break; + case 171:p1=Get_short();pc+=p1;break; + case 172:code_page=Get_short();break; + case 173:break; //ALT_SENTENCE + case 174:iff=join_character(Get_short());break; + case 189:dead_players=1; + case 175:echo(Get_string()); p1=Get_short(); + if (dlg_ask_who()) if (p1) goto_paragraph(p1); + else iff=1; + else iff=0; + break; + case 176:p1=Get_short();p2=Get_short();pract_to(sn_nums[0],p1,p2);break; + case 177:p1=Get_short();p2=Get_short();p3=Get_short();iff=test_vls(sn_nums[0],p1,p2,p3);break; + case 178:p1=Get_short();runes[p1/10]|=1<<(p1%10);break; + case 179:p1=Get_short();iff=((runes[p1/10] & (1<<(p1%10)))!=0);break; + case 180:p1=Get_short();iff=(money>=p1);break; + case 181:p1=Get_short();p2=Get_short();p3=Get_short();pract(sn_nums[0],p1,p2,p3);break; + case 182:p1=Get_short();p2=Get_short();dark_screen(p1,p2);break; + case 183:spat(Get_short());break; + case 184:p1=Get_short();iff=najist_postavy(p1);break; + case 185:iff=isall();break; + case 186:enable_glmap=Get_short();break; + case 187:p1=Get_short();p2=Get_short();iff=atsector(p1,p2);break; + case 188:p1=Get_short();cast_spell(p1);break; + case 190:spell_sound(Get_string());break; + case 191:p1=Get_short();p2=Get_short();iff=test_volby_select(p1,p2);break; + case 192:p1=Get_short();p2=Get_short();varibles[p1]=p2;break; + case 193:p1=Get_short();p2=Get_short();varibles[p1]+=p2;break; + case 194:p1=Get_short();p2=Get_short();p3=Get_short();iff=oper_balance(varibles[p1],p3,p2);break; + case 195:p2=find_pgnum(pc);p1=Get_short();varibles[p1]=p2;break; + case 196:p1=Get_short();varibles[p1]=iff;break; + case 197:p1=Get_short();add_case(varibles[p1],Get_string());break; + case 198:p1=Get_short();p2=Get_short();c=Get_string();if (iff==p1) add_case(varibles[p2],c);break; + case 199:goto_paragraph(varibles[Get_short()]);break; + case 200:iff=drop_character();break; + case 201:pc_xicht(Get_short());break; + case 518:set_flag(Get_short());break; + case 519:reset_flag(Get_short());break; + case 255:exit_dialog();return; + default: + { + char s[80]; + sprintf(s,"Nezn m  instrukce: %d",i); + error(s); + } + break; + } + } + while(1); + } + +static void create_back_pic() + { + int skpx=4,skpy=5,xp,yp; + word *p,*s=GetScreenAdr()+SCREEN_OFFSET,*s2; + + schovej_mysku(); + p=back_pic=NewArr(word,3+340*200); + *p++=340; + *p++=200; + *p++=A_16BIT; + for(yp=0;yp<200;yp++) + { + s2=s; + for(xp=0;xp<340;xp++) + { + *p++=*s2++; + if (!skpx) skpx=8;else s2++,skpx--; + } + s+=scr_linelen2; + if (!skpy) skpy=4;else s+=scr_linelen2,skpy--; + } + ukaz_mysku(); + } + +void call_dialog(int entr,int mob) + { + int i; + void (*old_wire_proc)()=wire_proc; + curcolor=0; + create_back_pic(); + bar(0,SCREEN_OFFLINE,639,SCREEN_OFFLINE+359); + SEND_LOG("(DIALOGS) Starting dialog...",0,0); + for(i=0;i-1) + { + _flag_map[0]=mobs[mob].dialog_flags; + _flag_map[1]=mobs[mob].stay_strategy; + } + local_pgf=0; + poloz_vsechny_predmety(); + cancel_render=1; + norefresh=1; + history=create_list(256); + his_line=0; + memset(sn_nums,0xff,sizeof(sn_nums)); + goto_paragraph(entr); + schovej_mysku(); + alock(H_DIALOGY_DAT); + aswap(H_DIALOGY_DAT); + selected_player=-1; + do_dialog(); + } + +char save_dialog_info(FILE *f) + { + int pgf_pocet; + int *p,i; + size_t siz; + char *c,res=0; + T_PARAGRAPH *q; + + SEND_LOG("(DIALOGS)(SAVELOAD) Saving dialogs info...",0,0); + p=ablock(H_DIALOGY_DAT); + pgf_pocet=*p; + fwrite(&pgf_pocet,1,4,f); + siz=(pgf_pocet+3)/4; + if (siz) + { + c=getmem(siz); + memset(c,0,siz); + p=ablock(H_DIALOGY_DAT); + q=(T_PARAGRAPH *)(p+2); + for(i=0;i>2]|=(q[i].visited<>2]>>j); + q[i].first=(c[i>>2]>>(j+1)); + } + free(c); + } + res|=(fread(_flag_map,1,sizeof(_flag_map),f)!=sizeof(_flag_map)); + SEND_LOG("(DIALOGS)(SAVELOAD) Done...",0,0); + return res; + } diff --git a/GAME/DLGLIB.C b/GAME/DLGLIB.C new file mode 100644 index 0000000..9630019 --- /dev/null +++ b/GAME/DLGLIB.C @@ -0,0 +1,271 @@ +/* + + definice formatu- + + :num - odstavec + #text + + # asterix = muze obsahovat tyto znaky + . = normal text (vypisuje se) + _ = popis (zapisuje se do LOGu) + " = dialog (vypisuje se do LOGu a tiskne se) + ? = vyber.. Nasleduje . nebo _ nebo ' + * = prikaz + ; = komentar + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +FILE *dlg; +long *odstavce=NULL; +int pocet; + +int selptr=0; + +char get_article() + { + int c; + + while ((c=fgetc(dlg))==32); + return (char)c; + } + +#define new_line() while (fgetc(dlg)!='\n'); + + +int count_pargh() + { + char c; + int i=0; + + fseek(dlg,0,SEEK_SET); + c=get_article(); + while (c!=0xff) + { + if (c==':') i++; + if (c!='\n') new_line(); + c=get_article(); + } + return i; + } + +void read_pargh() + { + int s,i; + long *d; + char c; + if (odstavce!=NULL) free(odstavce); + odstavce=NULL; + s=(pocet=i=count_pargh())*sizeof(long)*2; + if (s==0) return; + odstavce=getmem(s); + d=odstavce; + fseek(dlg,0,SEEK_SET); + c=get_article(); + while (c!=0xff && i) + { + if (c==':') + { + fscanf(dlg,"%d",&s); + *d++=s; + *d++=ftell(dlg); + i--; + } + if (c!='\n') new_line(); + c=get_article(); + } + } + +void dlg_error(char *chyba) + { + closemode(); + printf("Error in dialoge: %s\n",chyba); + exit(1); + } + +long *najdi_odstavec(int odstavec) + { + long *d; + int i; + + + d=odstavce; + for(i=0;i>24; + fseek(dlg,m,SEEK_SET); + return c; + } + +void set_flags(int n,long maskand,long maskor) + { + long *l; + l=najdi_odstavec(n); + l[1]&=(maskand<<24)+0xffffff; + l[1]|=maskor<<24; + } + +int param(char *c) + { + int i; + sscanf(c,"%d",&i); + return i; + } + +int nparam(int n,char *c) + { + char *d; + + if (n) + { + d=c; + while (n--) d=(char *)strchr(d+1,','); + } + else d=c-1; + if (d==NULL) return -1;else return param(d+1); + } + +void proved_goto(int num) + { + char c; + long l; + l=ftell(dlg); + c=jdi_na_odstavec(num); + while (c & 1) + { + int i,j; + + j=fscanf(dlg,"%d",&i); + if (j) c=jdi_na_odstavec(i); else + { + c=0; + fseek(dlg,l,SEEK_SET); + } + } + } +void proved_d(char *code,char *text) + { + static int mode=0; + static char *save_text; + + do + { + if (mode==0) + { + *code=get_article(); + switch (*code) + { + case ';': + case ':':*code=0xff;new_line();break; + case '.':*code=1;break; + case '_':*code=2;break; + case '"':*code=3;break; + case '?':*code=4;selptr++;break; + case '*':*code=0;break; + default :*code=0xff;break; + } + if (*code!=0xff)fscanf(dlg,"%[^\n]",text); + if (*code==0) + { + strupr(text); + if (!strncmp(text,"GOTO",4)) + { + int n; + sscanf(text+4,"%d",&n); + proved_goto(n); + } + if (!strncmp(text,"JUMP",4)) + { + int n; + sscanf(text+4,"%d",&n); + jdi_na_odstavec(n); + } + else if (!strncmp(text,"DISABLE",7)) set_flags(param(text+7),0xff,1); + else if (!strncmp(text,"ENABLE",6)) set_flags(param(text+7),0xfe,0); + else if (!strncmp(text,"CHOICE",6)) + { + *text=selptr; + selptr=0; + *code=5; + mode=1; + save_text=getmem(strlen(text)-6+1); + strcpy(save_text,text+6); + } + else if (!strncmp(text,"STOP",4)) *code=7; + else if (!strncmp(text,"MENU",4)) selptr=param(text+4); + } + else if (*code==4) + { + long *l=najdi_odstavec(param(text)); + char c,*d; + + c=l[1]>>24; + if (c & 1) *code=6; + d=text;while (*d>='0' && *d<='9') d++; + strcpy(text,d); + } + } + else if (mode==1) + { + int i=text[1],j; + + *code=5; + j=nparam(i,save_text); + if (j==-1) return; + free(save_text); + proved_goto(j); + set_flags(j,0xff,0x1); + mode=0; + *code=0; + } + } + while (*code==0); + } + +main() + { + char code,text[300]; + dlg=fopen("test.txt","r"); + read_pargh(); + proved_goto(1); + proved_d(&code,text); + while (code!=7) + { + switch (code) + { + case 1:printf("%s\n",text);break; + case 2: + case 3:printf("%s\n",text);break; + case 4:printf(" %c.%s\n",selptr+64,text);break; + case 5:text[1]=toupper(getche())-65;putchar('\n');break; + } + proved_d(&code,text); + } + } + + diff --git a/GAME/DUMP.C b/GAME/DUMP.C new file mode 100644 index 0000000..d9837d4 --- /dev/null +++ b/GAME/DUMP.C @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +static int latest_version(char *wild,int numpos) + { + WIN32_FIND_DATA ff; + HANDLE rc; + int i=0,j=-1; + char *p; + + rc=FindFirstFile(wild,&ff); + if (rc!=INVALID_HANDLE_VALUE) + do + { + p=ff.cFileName+numpos; + sscanf(p,"%d",&i); + if (i>j) j=i; + } + while (FindNextFile(rc,&ff)); + FindClose(rc); + return j; + } + +void save_dump() + { + static dump_counter=-1; + FILE *f; + int i,r,g,b,x,y; + word *a; + char c[20]; + + if (dump_counter==-1) + { + dump_counter=latest_version("DUMP*.BMP",4); + SEND_LOG("(DUMP) Dump counter sets to %d",dump_counter,0); + } + sprintf(c,"DUMP%04d.BMP",++dump_counter); + SEND_LOG("(DUMP) Saving screen shot named '%s'",c,0); + f=fopen(c,"wb"); + fputc('B',f);fputc('M',f); + i=DxGetResX()*DxGetResY()*3+0x36; + fwrite(&i,1,4,f);i=0; + fwrite(&i,1,4,f); + i=0x36; + fwrite(&i,1,4,f); + i=0x28; + fwrite(&i,1,4,f); + i=DxGetResX(); + fwrite(&i,1,4,f); + i=DxGetResY(); + fwrite(&i,1,4,f); + i=1; + fwrite(&i,1,2,f); + i=24; + fwrite(&i,1,2,f); + i=0; + fwrite(&i,1,4,f); + i=DxGetResX()*DxGetResY()*3; + fwrite(&i,1,4,f); + for(i=4,r=0;i>0;i--) fwrite(&r,1,4,f); + for(y=DxGetResY();y>0;y--) + { + word *scr=GetScreenAdr(); + a=scr+(y-1)*scr_linelen2; + for(x=0;x>3; + r=i>>8; + i=((r*256)+g)*256+b; + fwrite(&i,1,3,f); + } + } + fclose(f); + } + diff --git a/GAME/ENCRYPT.C b/GAME/ENCRYPT.C new file mode 100644 index 0000000..dbc040a --- /dev/null +++ b/GAME/ENCRYPT.C @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include + +FILE *source,*target; + +void encrypt_file(FILE *sr,FILE *tg) + { + int i,j,last=0; + + i=getc(sr); + while (i!=EOF) + { + j=i-last; + last=i; + putc(j,tg); + i=getc(sr); + } + } + +void open_files(char *src,char *tgr) + { + if (tgr==NULL) + { + char *c,*d; + tgr=alloca(strlen(src)+5); + strcpy(tgr,src); + c=strrchr(tgr,'\\'); + d=strrchr(tgr,'.'); + if (c>d) d=strchr(tgr,0); + strcpy(d,".ENC"); + } + source=fopen(src,"rb"); + target=fopen(tgr,"wb"); + } + +void close_files() + { + fclose(source); + fclose(target); + } + + +char main(int argc,char **argv) + { + if (argc<2) + { + puts("Pouziti: ENCRYPT zdroj.ext [cil.ext] \n" + "\n" + "Pokud nezadas cil, doplni se zdroj s koncovkou .enc\n" + "Nikdy nezadavej pouze cestu jako cil. Vzdycky uved jmeno!"); + return 0; + } + if (argc==2) open_files(argv[1],NULL); + else open_files(argv[1],argv[2]); + if (source==NULL) + {puts("Nemuzu najit zdrojovy soubor\n");return 1;}; + if (target==NULL) + {puts("Nemuzu otevrit cil pro zapis\n");return 1;}; + encrypt_file(source,target); + close_files(); + puts("Ok."); + return 0; + } diff --git a/GAME/ENEMY.C b/GAME/ENEMY.C new file mode 100644 index 0000000..fa617e3 --- /dev/null +++ b/GAME/ENEMY.C @@ -0,0 +1,2140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include "globals.h" +#include "specproc.h" + +#define MOB_ZNAKY "FLBLCH" +#define MOB_START 1 + + +#define MOB_DIST 24 +#define MBS_WALK 0 +#define MBS_ATTACK 1 +#define MBS_HIT 2 + + +#define MBA_ATTACK 3 //potvora utoci +#define MBA_SPELL 1 //potvora caruje +#define MBA_FLEE 2 //potvora utika +#define MBA_NONE 0 + +#define PK_QUERY 0 //dotaz zda je v mrtvole predmet +#define PK_PICK 1 //prvni predmet v mrtvole + +#define mob_walk_sound(p) if (p->locx!=p->headx || p->locy!=p->heady) mob_sound_event(p,MBS_WALK) + +TMOB mobs[MAX_MOBS]; +char *mob_map; +char hex_chars[]="0123456789ABCDEF"; +int mob_dostal=0; +int mob_dostal_pocet; + +char folow_mode=0; +char folow_mob; + +char mob_go_x[]={128,255,128,0}; +char mob_go_y[]={0,128,255,128}; +char mob_batt_x[]={128,128+MOB_DIST,128,128-MOB_DIST}; +char mob_batt_y[]={128-MOB_DIST,128,128+MOB_DIST,128}; +short konv_x[]={1,1,-1,-1}; +short konv_y[]={-1,1,1,-1}; +char going[]={0,0,1,0,1,1}; + +static word *mob_paths[MAX_MOBS]; +static word *mob_path_ptr[MAX_MOBS]; +static int monster_block; + +void *sound_template=NULL; + +short att_sect; +char battle=0; +char neco_v_pohybu=1; +char nohassle=0; + +typedef struct tmobsavedata +{ + short anim_counter; //citac animaci + char anim_phase; //cinnost kterou mob dela + char dir; +}TMOBSAVEDATA; + +static TMOBSAVEDATA **mobsavedata=0; + +static void register_mob_path(int mob,word *path) //registruje cestu pro potvoru + { + mob_paths[mob]=path; + mob_path_ptr[mob]=path; + } + +static void free_path(int mob) //vymaze cestu potvore + { + free(mob_paths[mob]); + mob_paths[mob]=NULL; + mob_path_ptr[mob]=NULL; + } + +void send_mob_to(int m,word *path) + { + if (mob_paths[m]!=NULL) + { + free_path(m); + } + register_mob_path(m,path); + mobs[m].stay_strategy |= MOB_WALK; + } + +void smeruj_moba(TMOB *m,int smer) + { + int val=128+MOB_DIST*smer; + + switch (m->dir) + { + case 0:m->headx=val;break; + case 1:m->heady=val;break; + case 2:m->headx=-val;break; + case 3:m->heady=-val;break; + } + } + +void save_enemy_paths(FILE *f) + { + int i,s; + word *w; + + for(i=0;ihome_pos].flags & MC_PLAYER || + mob_map[m->home_pos]) return; + m->vlajky|=MOB_LIVE; + m->vlajky&=~MOB_IN_BATTLE; + m->lives=m->vlastnosti[VLS_MAXHIT]; + m->sector=m->home_pos; + m->locx=m->headx=m->locy=m->heady=128; + memset(m->inv,0,sizeof(m->inv)); + play_sample_at_sector(H_SND_TELEPOUT,viewsector,m->home_pos,0,0); + add_spectxtr(m->home_pos,H_TELEP_PCX,14,1,0); + refresh_mob_map(); + debug_text="New monster arrived to the dungeon !"; + SEND_LOG("(RELOAD) Mob reloaded: '%s' at sector %d",m->name,m->home_pos); + free_path(m-mobs); + } + } + } + + +void init_mobs() + { + memset(mobs,0,sizeof(mobs)); + mob_map=getmem(mapsize); + memset(mob_map,0,mapsize); + memset(mob_paths,0,sizeof(mob_paths)); + memset(mob_path_ptr,0,sizeof(mob_path_ptr)); + send_message(E_DONE,E_KOUZLO_KOLO,mob_reload); + send_message(E_ADD,E_KOUZLO_KOLO,mob_reload); + } + +static void register_mob_graphics(int num,char *name_part,char *anims,char *seq) + { + char fulname[14]; + char znaky[]=MOB_ZNAKY; + int i,j,a; + + strcpy(fulname,name_part); + strcat(fulname,"??.PCX"); + a=num; + for(i=0;i<6;i++) + { + for(j=0;j<16;j++) + { + if (anims[i]) + { + fulname[6]=znaky[i]; + if (j<=anims[i]) + { + fulname[7]=*seq++; + def_handle(a,fulname,pcx_8bit_nopal,SR_ENEMIES); + } + a++; + } + else + { + fulname[6]=znaky[0]; + if (j<=anims[0]) + { + fulname[7]=*seq++; + def_handle(a,fulname,pcx_8bit_nopal,SR_ENEMIES); + } + a++; + } + if (*seq=='\r') + { + char buff[256]; + closemode(); + sprintf(buff,"Soubor sekvence %s obsahuje chybne udaje nebo je sekvence je moc kratka\n"); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONSTOP); + exit(0); + } + } + seq=strchr(seq,'\n')+1; + } + } + + + + +static void register_mob_sounds(int hlptr,word *sounds) + { + int i,z; + + for(i=0;i<4;i++) + { + z=sounds[i]; + if (z) + { + def_handle(hlptr,sound_table[z-1],wav_load,SR_ZVUKY); + } + hlptr++; + } + } + +static char miri_middle(TMOB *p) //procedura zjisti zda li potvora miri do dveri + { + int ss; + + ss=(p->sector<<2)+p->dir; + return (map_sides[ss].lclip!=0); + } + + +static char pick_item_corpse(TMOB *m,char query) + { + short *p=NULL; + int sector=m->sector; //sektor kde se bude mrtvola prohledavat + if (map_coord[sector].flags & MC_DEAD_PLR) //lezi tam vubec nejaka mrtvola? + { + int i; + THUMAN *h; //najdi mezi hraci mrtvolu ktera tam lezi + for(i=0,h=postavy;ilives && h->used && h->sektor==sector) + { + int i; //podivej se ji do inventare.... + for(i=0;iprsteny[i]) p=&h->prsteny[i]; + //nejprve ber prsteny + for(i=0;iwearing[i]) p=&h->wearing[i]; + //pak seber zbrane a brneni + for(i=0;iinv_size && p==NULL;i++) if (h->inv[i]) p=&h->inv[i]; + //teprve potom se podivej co ma v inv. + } + } + if (p!=NULL) //nasel jsi neco? + if (query==PK_QUERY) return 1; //pokud se jednalo o dotaz, tak pouze vrat 1 + else + { + int i; + for(i=0;iinv[i]==0) break; //zjisti jestli mas misto + if (i==MOBS_INV) return 0; //nemas, mas smulu.... + m->inv[i]=*p; //prenes predmet od postavy do sveho inventare. + *p=0; //ale na puvodnim miste tento predmet znic. + } + else return 0; + return 1; + } + +static char seber_predmet(TMOB *m) + { + short *p=NULL,*q; + int i,j,c,z; + + for(j=0,c=0;jinv[j]==0)); + i=0; + do + { + for(;i<4 && p==NULL;i+=(p==NULL)) pop_item(m->sector,i,0,&p); + if (i==4) return 1; + z=count_items_total(p); + if (z>c) + { + push_item(m->sector,i,p); + free(p); + p=NULL; + } + i++; + } + while (z>c); + if (z<=c) for(q=p,j=0;jinv[j]==0) m->inv[j]=(abs(*q++)); + free(p); + return 0; + } + +static void mob_sound_event(TMOB *m,int event) + { + if (m->sounds[event] && m->vlajky & MOB_LIVE && ~m->vlastnosti[VLS_KOUZLA] & SPL_STONED) + if (event==MBS_WALK) + play_sample_at_sector(m->cislo_vzoru+16*6+event+monster_block,viewsector,m->sector,m-mobs+256,(m->vlajky & MOB_SAMPLE_LOOP)!=0); + else + play_sample_at_sector(m->cislo_vzoru+16*6+event+monster_block,viewsector,m->sector,0,0); + } + +void load_enemies(short *data,int size,int *grptr,TMOB *template,long tsize) + { + int i; + short cisla[256]; + + monster_block=*grptr; + memset(cisla,0xff,sizeof(cisla)); + size>>=2; + for(i=0;iMAX_MOBS-MOB_START) size=MAX_MOBS-MOB_START; + for(i=0;i=0)mobs[i].palette=rnd(mobs[i].palette);else mobs[i].palette=abs(mobs[i].palette); + mobs[i].sector=data[0]; + mobs[i].dir=(data[1]>>14)&0x3; + mobs[i].home_pos=data[0]; + mobs[i].vlajky|=MOB_LIVE; + if (mobs[i].speed<1) + { + char buff[256]; + closemode(); + sprintf(buff,"Nestvura cislo #%d (%s) je spatne definovana (rychlost)",i,mobs[i].name); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONEXCLAMATION); + exit(1); + } + cisla[i]=mobs[i].cislo_vzoru; + for(j=0;j0 && cnt<5;cnt++,dir=(dir+1)&3) + if (!(i=mob_check_next_sector(sector,dir,alone,mobile))) + { + r--; + if (!r) break; + } + if (cnt==5) dir=-1; + return dir; + } + +char je_mozne_videt(int sector1,int sector2,int flag) + { + int x1,y1; + int x2,y2; + int xs,ys; + int x,y,ly,s; + + if (map_coord[sector1].layer!=map_coord[sector2].layer) return 0; + x1=map_coord[sector1].x;x2=map_coord[sector2].x; + y1=map_coord[sector1].y;y2=map_coord[sector2].y; + xs=x1-x2; + ys=y1-y2; + if (xs==0 && ys==0) return 1; + s=sector1; + ly=0; + if (xs>=0) + { + for(x=0;x<=xs;x++) + { + y=(x+1)*ys/(xs+1); + while (y>ly) + if ((map_sides[(s<<2)].flags & flag)!=(unsigned)flag) + { + s=map_sectors[s].step_next[0]; + ly++; + } + else return 0; + while (y=xs;x--) + { + y=(x-1)*ys/(xs-1); + while (y>ly) + if ((map_sides[(s<<2)].flags & flag)!=(unsigned)flag) + { + s=map_sectors[s].step_next[0]; + ly++; + } + else return 0; + while (yvlastnosti[VLS_KOUZLA] & SPL_BLIND) return -1; + if (p->vlastnosti[VLS_KOUZLA] & SPL_FEAR) return -1; + if (p->flee_num==100 && !insleep) return -1; + for(i=0;idohled && (!(ps->vlastnosti[VLS_KOUZLA] & SPL_INVIS)||p->vlajky & MOB_SENSE) && ps->used && ps->lives) + switch(dir) + { + case 0:ok=ys>=0;break; + case 1:ok=xs<=0;break; + case 2:ok=ys<=0;break; + case 3:ok=xs>=0;break; + } + if (ok) + if (je_mozne_videt(sector,postavy[i].sektor,SD_MONST_IMPS | SD_PLAY_IMPS)) + { + int alt; + if (ys>=abs(xs)) {nd=0;alt=xs>0?3:1;} + else if (xs>=abs(ys)) {nd=3;alt=ys>0?0:2;} + else if (ys<=(-abs(xs))) {nd=2;alt=xs>0?1:3;} + else if (xs<=(-abs(ys))) {nd=1;alt=ys>0?2:0;} + if (mob_check_next_sector(p->sector,nd,p->stay_strategy & MOB_BIG,p->vlajky & MOB_PASSABLE)==1) + { + nd=alt; + if (mob_check_next_sector(p->sector,nd,p->stay_strategy & MOB_BIG,p->vlajky & MOB_PASSABLE)==1) + { + nd=(alt+2)&3; + if (mob_check_next_sector(p->sector,nd,p->stay_strategy & MOB_BIG,p->vlajky & MOB_PASSABLE)==1) + { + nd=(alt+3)&3; + } + } + } + } + else d=255; + else d=255; + if (d!=255) + { + d*=2; + if (xs!=0 && ys!=0) d+=3;//dej prednost tem co jsou na tve souradnici. + if (dheadx!=255 && p->headx!=0 && p->headx!=128) return 128-p->headx; + if (p->heady!=255 && p->heady!=0 && p->heady!=128) return 128-p->heady; + } + if (p->headx!=255 && p->headx!=0) p->headx=128+kolik; + if (p->heady!=255 && p->heady!=0) p->heady=128+kolik; + return -kolik; + } + + +void stop_mob(TMOB *p) + { + int num1; + TMOB *q; + + p->mode=MBA_NONE; + num1=mob_map[p->sector]; + if (num1) q=&mobs[num1-MOB_START];else q=p; + if (p==q) + if (p->next) + q=mobs+p->next-MOB_START; + else + q=NULL; + if (p->stay_strategy & MOB_BIG) + { + p->headx=128; + p->heady=128; + goto end; + } + if (q!=NULL && p->dir!=q->dir) + { + p->headx=mob_batt_x[p->dir]; + p->heady=mob_batt_y[p->dir]; + q->headx=mob_batt_x[q->dir]; + q->heady=mob_batt_y[q->dir]; + mob_walk_sound(p); + mob_walk_sound(q); + return; + } + if (q!=NULL && p->dir==q->dir) + { + if (miri_middle(q)) + { + p->dir=p->dir+1 & 3; + stop_mob(q); + } + } + else + { + if (p->dir & 1) + { + p->headx=mob_batt_x[p->dir]; + if (p->heady==255 || p->heady==0) p->heady=128; + } + else + { + p->heady=mob_batt_y[p->dir]; + if (p->headx==255 || p->headx==0) p->headx=128; + } + goto end; + } + { + switch (p->dir) + { + case 0: + case 2:if (q->headx==128) + if (p->headx<128) q->headx=128+MOB_DIST;else q->headx=128-MOB_DIST; + p->headx=-q->headx; + p->heady=mob_batt_y[p->dir]; + break; + case 1: + case 3:if (q->heady==128) + if (p->heady<128) q->heady=128+MOB_DIST;else q->heady=128-MOB_DIST; + p->heady=-q->heady; + p->headx=mob_batt_x[p->dir];break; + } + } + end: + mob_walk_sound(p); + } + +void stop_all_mobs() + { + int i; + for(i=0;inext; + } + } + +char mob_test_na_bitvu(TMOB *p) + { + int x,d; + char c=0; + char pt; + + if (nohassle) return 0; + if (p->stay_strategy & MOB_WATCH) + if ((d=q_vidis_postavu(p->sector,p->dir,p,&x,0))>-1) + { + p->stay_strategy|=MOB_WALK; + if (mob_check_next_sector(p->sector,x,p->stay_strategy & MOB_BIG,p->vlajky & MOB_PASSABLE)!=1) + { + pt=(p->headx==p->locx && p->heady==p->locy); + if (p->dir!=x || pt) + { + p->dir=x; + if (!(p->stay_strategy & MOB_BIG) || pt) + { + p->headx=mob_go_x[x]; + p->heady=mob_go_y[x]; + } + else + { + p->headx=128; + p->heady=128; + } + } + if (q_zacit_souboj(p,d,att_sect)) + { + stop_mob(p); + p->vlajky|=MOB_IN_BATTLE; + if (!battle) zacni_souboj(p,d,att_sect); + } + c=1; + } + if (c) mob_sound_event(p,MBS_WALK); + return c; + } + return 0; + } + +char return_home(TMOB *p,int *smer) + { + word *path; + int i; + + i=p->dir; + if (!mob_check_next_sector(p->sector,i+1&3,p->stay_strategy & MOB_BIG,0) || !mob_check_next_sector(p->sector,i+3&3,p->stay_strategy & MOB_BIG,0)) return 1; + if (p->sector==p->home_pos) return 1; + najdi_cestu(p->sector,p->home_pos,SD_MONST_IMPS,&path,(p->stay_strategy & MOB_BIG)?1:2); + if (path==NULL) + { + return 1; + } + for(i=0;i<4 && map_sectors[p->sector].step_next[i]!=path[0];i++); + free(path); + if (i==4) return 1; + if (mob_check_next_sector(p->sector,i,p->stay_strategy & MOB_BIG,0)) return 1; + *smer=i; + return 0; + } + +static int jdi_po_ceste(int old,TMOB *p) + { + int i,s; + word *c; + + if (p->mode==MBA_FLEE && !p->actions--) //v pride uteku pocitej kroky + { + p->mode=0; + p->vlajky&=~MOB_IN_BATTLE; + return old; + } + c=mob_path_ptr[p-mobs]; //vem cestu + if (c==NULL) return old; //neni -> konec + if (*c==0) //na konci -> dealokace a konec + { + free_path(p-mobs); + p->mode=0; + p->vlajky&=~MOB_IN_BATTLE; + return old; + } + s=p->sector; + for(i=0;i<4;i++) if (map_sectors[s].step_next[i]==*c) break; + if (i==4) return old; + old=i; + c++; + mob_path_ptr[p-mobs]=c; //uloz_ukazatel + return old; + } + +void rozhodni_o_smeru(TMOB *p) + { + int sect,dir,r,v,lv,c,alone,oldwalk,passable; + int vdir=-1; + + alone=p->stay_strategy & MOB_BIG; + passable=p->vlajky & MOB_PASSABLE; + sect=p->sector; + dir=p->dir; + lv=p->walk_data; + if (mob_paths[p-mobs]!=NULL) c=jdi_po_ceste(-1,p);else c=-1; + if (c!=-1) + if (!mob_check_next_sector(sect,c,alone,passable)) + { + p->headx=mob_go_x[c]; + p->heady=mob_go_y[c]; + p->dir=c; + goto end1; + } + else + { + if (mob_path_ptr[p-mobs]-mob_paths[p-mobs]>1) mob_path_ptr[p-mobs]-=2; + } + if (p->vlajky & MOB_IN_BATTLE) + { + stop_mob(p); + goto end1; + } + if (call_mob_event(p->specproc,SMPR_WALK,p)) goto end1; + oldwalk=p->walk_data; + if (mob_test_na_bitvu(p)) return; + p->vlajky&=~MOB_IN_BATTLE; + c=map_sectors[sect].sector_type; + c-=S_SMER; + if (c>=0 && c<4 && !mob_check_next_sector(sect,c,alone,passable)) + { + if (p->headx==p->locx && p->heady==p->locy) dir=c+4;else dir=c; + } + else + { + v=mob_pocet_vychodu(sect,dir); + if (v==p->walk_data && !mob_check_next_sector(sect,dir,alone,passable)) + if (p->headx==p->locx && p->heady==p->locy) dir=p->dir+4;else dir=p->dir; + else + { + r=1; + if (v==0) v=1; + p->walk_data=v; + if (v==1 && p->stay_strategy & MOB_GUARD) r=return_home(p,&dir); + if (r) + { + if (v<2) r=1;else r=rand()*v/(RAND_MAX+1)+1; + vdir=dir=mob_vyber_vychod(r,sect,dir,alone,passable); + //if ( p->stay_strategy & MOB_WATCH && rnd(100)<20 && lv<128 && dir!=p->dir) dir=-1; + } + } + } + if (dir==-1) + { + dir=p->dir;p->dir=p->dir+2&3; + stop_mob(p); + p->walk_data=rnd(32)+223; + if (vdir!=-1)p->dir=vdir; + } + else + if (p->dir!=dir || miri_middle(p)) + { + if (p->stay_strategy & MOB_BIG && (p->locx!=p->headx || p->locy!=p->heady)) + { + stop_mob(p); + p->walk_data=oldwalk; + } + else if ((p->dir-dir &0x3)==2 && (p->headx!=p->locx || p->heady!=p->locy)) + { + stop_mob(p); + p->walk_data=0; + } + else + { + dir&=3; + p->headx=mob_go_x[dir]; + p->heady=mob_go_y[dir]; + p->dir=dir; + } + } + end1: + if (p->headx!=p->locx || p->heady!=p->locy) mob_sound_event(p,MBS_WALK); + } + +void krok_moba(TMOB *p) + { + if (!mob_check_next_sector(p->sector,p->dir,p->stay_strategy,p->vlajky)) + { + p->headx=mob_go_x[p->dir]; + p->heady=mob_go_y[p->dir]; + } + } + +static char get_view_mirror=0; + +int get_view(TMOB *p,int dirmob,int action,int curdir) + { + int view;int pos; + int xs,ys; + + get_view_mirror=0; + if (action==MOB_ATTACK) pos=4; + else if (action==MOB_TO_HIT) pos=5; + else if (action==MOB_DEATH) + { + return 1; + } + else + { + xs=p->headx-p->locx; + ys=p->heady-p->locy; + if (!(game_extras & EX_WALKDIAGONAL) || p->stay_strategy & MOB_BIG) + if (ys!=0 && xs!=0) + if (p->dir==1 || p->dir==3) xs=0;else ys=0; + if (xs) dirmob=(xs<0)?3:1; + if (ys) dirmob=(ys<0)?0:2; + pos=(2+dirmob-curdir)&0x3; + if (game_extras & EX_WALKDIAGONAL && !( p->stay_strategy & MOB_BIG)) + { + switch (curdir & 0x3) + { + case 0: if (p->locx>p->headx) pos=1;else if (p->locxheadx) pos=3;break; + case 1: if (p->locy>p->heady) pos=1;else if (p->locyheady) pos=3;break; + case 2: if (p->locx>p->headx) pos=3;else if (p->locxheadx) pos=1;break; + case 3: if (p->locy>p->heady) pos=3;else if (p->locyheady) pos=1;break; + } + } + } + if (pos==3) get_view_mirror=pos=1; + if (p->anim_counter==-1) view=pos*16; + else view=pos*16+(p->anim_counter % p->anim_counts[pos])+1; + return view; + } + +void get_pos(int x,int y,int *xpos,int *ypos,int dir) + { + switch(dir) + { + case 0:*xpos=x;*ypos=-y;break; + case 1:*xpos=y;*ypos=x;break; + case 2:*xpos=-x;*ypos=y;break; + case 3:*xpos=-y;*ypos=-x;break; + } + } + +/* +void draw_blood(int zasah,int celx,int cely,int posx,int posy) + { + draw_placed_texture(ablock(H_MZASAH1+zasah-1),celx,cely,posx+64,posy+64,75,0); + } +*/ +static void *mob_select_palette(TMOB *p) + { + char *palet; + + palet=ablock(p->cislo_vzoru+6*16+4+monster_block); + return palet+(p->palette)*PIC_FADE_PAL_SIZE; + } + +static void CheckMobStoned(int num) +{ + if (mobs[num].vlastnosti[VLS_KOUZLA] & SPL_STONED) + { + TMOB *p=mobs+num; + TMOBSAVEDATA *save; + if (!mobsavedata) + { + mobsavedata=(TMOBSAVEDATA **)getmem(sizeof(TMOBSAVEDATA *)*MAX_MOBS); + memset(mobsavedata,0,sizeof(TMOBSAVEDATA)*MAX_MOBS); + } + save=mobsavedata[num]; + if (save==NULL) + { + save=mobsavedata[num]=(TMOBSAVEDATA *)getmem(sizeof(TMOBSAVEDATA)); + save->anim_counter=p->anim_counter; + save->anim_phase=p->anim_phase; + save->dir=p->dir; + } + else + { + p->anim_counter=save->anim_counter; + p->anim_phase=save->anim_phase; + p->dir=save->dir; + p->headx=p->locx; + p->heady=p->locy; + } + } + else + { + if (mobsavedata && mobsavedata[num]) + { + free(mobsavedata[num]); + mobsavedata[num]=0; + } + } + + +} + +void draw_mob_call(int num,int curdir,int celx,int cely,char shiftup) + { + TMOB *p,*q; + int view,vw; + int view2,vw2; + DRW_ENEMY drw1,drw2; + + set_font(H_FLITT5,RGB555(31,31,0)); + CheckMobStoned(num-MOB_START); + p=&mobs[num-MOB_START]; + shiftup|=(p->stay_strategy & MOB_BIG); + + get_pos(p->locx-128,p->locy-128,&drw1.posx,&drw1.posy,curdir); + view=get_view(p,p->dir,p->anim_phase,curdir); + vw=p->cislo_vzoru+view+monster_block; + if (p->vlastnosti[VLS_KOUZLA] & SPL_INVIS) {drw1.txtr=NULL;vw=0;}else drw1.txtr=ablock(vw); + drw1.celx=celx; + drw1.cely=cely; + drw1.mirror=get_view_mirror; + drw1.adjust=p->adjusting[view]; + drw1.shiftup=shiftup; + drw1.num=p->lives; + drw1.palette=mob_select_palette(p); + drw1.stoned= (p->vlastnosti[VLS_KOUZLA] & SPL_STONED)!=0; + see_monster|=(~p->vlajky & MOB_PASSABLE); + if (p->next) + { + CheckMobStoned(p->next-MOB_START); + q=&mobs[p->next-MOB_START]; + get_pos(q->locx-128,q->locy-128,&drw2.posx,&drw2.posy,curdir); + view2=get_view(q,q->dir,q->anim_phase,curdir); + vw2=view2+q->cislo_vzoru+monster_block; + drw2.shiftup=shiftup; + drw2.celx=celx; + drw2.cely=cely; + alock(vw); + alock(vw+6*16+5); + if (q->vlastnosti[VLS_KOUZLA] & SPL_INVIS) {drw2.txtr=NULL;vw2=0;}else drw2.txtr=ablock(vw2); + drw2.mirror=get_view_mirror; + alock(vw2); + alock(vw2+6*16+5); + drw2.adjust=q->adjusting[view2]; + drw2.num=q->lives; + drw2.palette=mob_select_palette(q); + drw2.stoned=(q->vlastnosti[VLS_KOUZLA] & SPL_STONED)!=0; + see_monster|=(~q->vlajky & MOB_PASSABLE); + } + else + { + view2=-1; + draw_enemy(&drw1); + return; + } + if (drw1.posy>drw2.posy) + { + draw_enemy(&drw1); + draw_enemy(&drw2); + } + else + { + draw_enemy(&drw2); + draw_enemy(&drw1); + } + aunlock(vw); + aunlock(vw2); + aunlock(vw+6*16+5); + aunlock(vw2+6*16+5); + } + +void draw_mob(int num,int curdir,int celx,int cely,char shiftup) + { + int ss=(num<<2); + num=mob_map[num]; + if (!num) return; + set_lclip_rclip(celx,cely,map_sides[ss+((curdir+3)&3)].lclip,map_sides[ss+((curdir+1)&3)].lclip); + draw_mob_call(num,curdir,celx,cely,shiftup); + } + + +void otoc_moba(TMOB *p) + { + p->walk_data=255; + rozhodni_o_smeru(p); + } + + +static mob_check_teleport(int sect,int num) + { + int i; + if (!ISTELEPORTSECT(sect)) return sect; + play_sample_at_sector(H_SND_TELEPOUT,viewsector,sect,0,0); + add_spectxtr(sect,H_TELEP_PCX,14,1,0); + sect=map_sectors[sect].sector_tag; + play_sample_at_sector(H_SND_TELEPOUT,viewsector,sect,0,0); + add_spectxtr(sect,H_TELEP_PCX,14,1,0); + if (map_coord[sect].flags & MC_PLAYER) + { + THUMAN *h=postavy; + for(i=0;isektor==sect) player_hit(h,h->lives,0); + } + mobs[num].locx=128; + mobs[num].locy=128; + return sect; + } + +void mob_step_next(int num,int sect,int dir,char *change) + { + int c,numm,d; + TMOB *p; + + *change+=128; + numm=num+MOB_START; + if (~mobs[num].vlajky & MOB_MOBILE) + { + c=mob_map[sect]; + if (c!=numm) + mobs[c-MOB_START].next=0; + else mob_map[sect]=mobs[num].next; + mobs[num].next=0; + recheck_button(sect,1); + } + sect=map_sectors[sect].step_next[dir]; + if (~mobs[num].vlajky & MOB_MOBILE) + { + sect=mob_check_teleport(sect,num); + c=mob_map[sect]; + if (c) + { + mobs[num].next=c; + d=uhni_mobe(1,num,0); + if (d) d=uhni_mobe(1,c-MOB_START,d); + else d=uhni_mobe(1,c-MOB_START,-MOB_DIST); + } + mob_map[sect]=numm; + recheck_button(sect,1); + } + mobs[num].sector=sect; + p=&mobs[num]; + p->dir=dir; + rozhodni_o_smeru(p); + if (p->next) + uhni_mobe(0,num,d); + if (p->stay_strategy & MOB_PICKING) + { + for(c=0;c<4;c++) if (map_items[(p->sector<<2)+c]!=NULL) break; + if (c==4 && pick_item_corpse(p,PK_QUERY)) c=0; + if (c!=4) + { + stop_mob(p); + p->stay_strategy|=MOB_PICK; + } + } + } + +void mob_check(int num,TMOB *p) + { + int sect,q,z; + + sect=p->sector; + q=p->stay_strategy & MOB_BIG; + z=p->vlajky & MOB_PASSABLE; + if (p->locy<64) + if (mob_check_next_sector(sect,0,q,z)) otoc_moba(p); + else mob_step_next(num,sect,0,&p->locy); + else if (p->locx>191) + if (mob_check_next_sector(sect,1,q,z)) otoc_moba(p); + else mob_step_next(num,sect,1,&p->locx); + else if (p->locy>191) + if (mob_check_next_sector(sect,2,q,z)) otoc_moba(p); + else mob_step_next(num,sect,2,&p->locy); + else if (p->locx<64) + if (mob_check_next_sector(sect,3,q,z)) otoc_moba(p); + else mob_step_next(num,sect,3,&p->locx); + if (battle && p->mode!=MBA_FLEE) + { + mob_sound_event(p,MBS_WALK); + stop_mob(p); + } + } + +/*void mobs_attack(TMOB *p) + { + int sect,dir,asect; + + if (p->actions<=0) return; + neco_v_pohybu=1; + sect=p->sector; + dir=p->dir; + asect=map_sectors[sect].step_next[dir]; + if (!asect || map_sides[sect*4+dir].flags & SD_MONST_IMPS) + { + rozhodni_o_smeru(p); + p->headx=mob_go_x[p->dir]; + p->heady=mob_go_y[p->dir]; + p->anim_phase=0; + return; + } + if (!(map_coord[asect].flags & MC_PLAYER)) + { + rozhodni_o_smeru(p); + p->headx=mob_go_x[p->dir]; + p->heady=mob_go_y[p->dir]; + p->anim_phase=0; + return; + } + p->anim_phase=MOB_ATTACK; + p->csektor=asect; + viewsector=asect; + viewdir=(dir+2)&3; + }*/ + +void vymaz_zasahy(THE_TIMER *q) + { + if (q->userdata[1]!=postavy[q->userdata[0]].dostal) return; + postavy[q->userdata[0]].dostal=0; + bott_draw(0); + } + +static drop_inventory(TMOB *p) + { + int i,x,y,pl; + short c[]={0,0}; + + for(i=-1;iinv[i] || (i<0 && p->money)) + { + if (p->locx>128) x=1;else if (p->locx<128) x=-1;else x=rnd(2)*2-1; + if (p->locy>128) y=1;else if (p->locy<128) y=-1;else y=rnd(2)*2-1; + pl=0;if (x>0) pl++; + if (y>0) pl=3-pl; + if (i<0) + { + int z=(int)p->money+(int)(rnd(40)-20)*(int)p->money/(int)100; + c[0]=create_item_money(z); + } + else + { + c[0]=p->inv[i]; + p->inv[i]=0; + } + push_item(p->sector,pl,c); + } + } + + +void mob_check_death(int num,TMOB *p) + { + int sect; + + mob_dostal=0; + bott_draw(0); + if (p->lives>0) return; + SEND_LOG("(GAME) Monster killed ... '%s'",p->name,0); + sect=p->sector; + p->vlajky&=~MOB_IN_BATTLE & ~MOB_LIVE; + free_path(num); + drop_inventory(p); + if (mob_map[sect]==num+MOB_START) mob_map[sect]=p->next; + else + { + p=&mobs[mob_map[sect]-MOB_START]; + p->next=0; + } + pozdrz_akci(); + } +extern char att_player; + +void mob_hit(TMOB *mm,int dostal) + { + int ch; + int mob_dostal,mob_dostal_pocet; + + if (mm->vlajky & MOB_PASSABLE) return; + if (dostal>mm->vlastnosti[VLS_MAXHIT]) dostal=mm->vlastnosti[VLS_MAXHIT]; + mm->headx=mm->locx; + mm->heady=mm->locy; + mm->lives-=dostal; + mob_dostal_pocet=dostal; + mm->dostal+=dostal; + if (dostal>0) mm->vlajky|=MOB_IN_BATTLE; + //mm->stay_strategy|=MOB_WALK | MOB_WATCH; + mm->dialog_flags|=0x2; + if (mm->lives>mm->vlastnosti[VLS_MAXHIT]) mm->lives=mm->vlastnosti[VLS_MAXHIT]; + dlives=mm->lives; + if (dostal>0) + { + ddostal=dostal; + send_experience(mm,dostal); + att_player=select_player; + if (dostallives) ch=dostal*3/mm->lives;else ch=2; + mob_dostal=ch+1; + bott_draw(0); + if (mm->lives<1) + { + int xpos; + switch (viewdir) + { + case 0:xpos=-(mm->locx-128);break; + case 1:xpos=-(mm->locy-128);break; + case 2:xpos=(mm->locx-128);break; + case 3:xpos=(mm->locy-128);break; + } + add_spectxtr(mm->sector,H_KILL,10,1,xpos*23/10); + mm->anim_phase=MOB_DEATH; + } + else mm->anim_phase=MOB_TO_HIT; + mm->anim_counter=0; + mm->mode=MBA_NONE; + mob_sound_event(mm,MBS_HIT); + battle|=dostal>0; + if (vybrana_zbran>-1) //utok zbrani? + { + int druh; + if (vybrana_zbran!=0) //neni to utok holyma rukama + { + TITEM *it; + it=&glob_items[vybrana_zbran-1]; + druh=it->typ_zbrane; + } + else druh=TPW_OST; + send_weapon_skill(druh); + vybrana_zbran=-1; + } + } + if (mob_dostal_pocet>0)draw_blood(1,mob_dostal,mob_dostal_pocet); + } + + +void mob_strelba(TMOB *p) + { + int i; + TITEM *t; + + for(i=0;izmeny[VLS_MGSIL_H]=p->vlastnosti[VLS_MGSIL_H]; //adjust zmen v magickem utoku + t->zmeny[VLS_MGSIL_L]=p->vlastnosti[VLS_MGSIL_L]; + t->zmeny[VLS_MGZIVEL]=p->vlastnosti[VLS_MGZIVEL]; + spell_throw(-((p-mobs)+1),i); + letici_veci->flags &=~FLY_DESTROY; + letici_veci->hit_bonus=p->vlastnosti[VLS_UTOK_L]+rnd(p->vlastnosti[VLS_UTOK_H]-p->vlastnosti[VLS_UTOK_L]+1); + letici_veci->damage=p->vlastnosti[VLS_DAMAGE]; + p->dostal=0; + } + +static void knock_player_back(THUMAN *p,int dir) + { + int sect,sid,nsect; + + sect=p->sektor;sid=sect*4+dir; + nsect=map_sectors[sect].step_next[dir]; + if (mob_map[nsect]) return; + destroy_player_map(); + call_macro(sid,MC_EXIT); + if (map_sides[sid].flags & SD_PLAY_IMPS) + { + call_macro(sid,MC_PASSFAIL); + build_player_map(); + return; + } + else call_macro(sid,MC_PASSSUC); + p->sektor=nsect; + viewsector=nsect; + check_postavy_teleport(); + build_player_map(); + recheck_button(nsect,1); + recheck_button(sect,1); + redraw_scene(); + hold_timer(TM_BACK_MUSIC,1); + zooming_backward(ablock(H_BGR_BUFF)); + hold_timer(TM_BACK_MUSIC,0); + showview(0,0,0,0); + } + +void PodporaStitu(THUMAN *h, short *vlastnosti) + { + int pos[]={PO_RUKA_L,PO_RUKA_R}; + int i; + int factor=h->kondice*100/h->vlastnosti[VLS_KONDIC]; + for (i=0;i<2;i++) + { + if (h->wearing[pos[i]]!=0) + { + TITEM *it=glob_items+h->wearing[pos[i]]-1; + if (it->zmeny[VLS_OBRAN_L] || it->zmeny[VLS_OBRAN_H]) + { + vlastnosti[VLS_OBRAN_L]-=it->zmeny[VLS_OBRAN_L]; + vlastnosti[VLS_OBRAN_H]-=it->zmeny[VLS_OBRAN_H]; + vlastnosti[VLS_OBRAN_L]+=(2*it->zmeny[VLS_OBRAN_L])*factor/100; + vlastnosti[VLS_OBRAN_H]+=(2*it->zmeny[VLS_OBRAN_H])*factor/100; + } + } + } + if (factor<20) + { + vlastnosti[VLS_OBRAT]=vlastnosti[VLS_OBRAT]*factor/20; + } + if (h->kondice) h->kondice--; + } + +void mobs_hit(TMOB *p) + { + int asect; + int obet; + int i,pocet; + THE_TIMER *tt; + int spec;char rr=1;char dead; + THUMAN *h; + short vlastnosti[VLS_MAX]; + + if (p->mode==MBA_SPELL) + { + mob_cast(p->casting,p,p-mobs); + p->dostal=0; + } + else + if (p->stay_strategy & MOB_ROGUE) mob_strelba(p); + else + { + asect=p->csektor; + if (!(map_coord[asect].flags & MC_PLAYER)) return; + pocet=0; + for(i=0;iused && p->sektor==asect && p->lives) pocet++; + } + if (!pocet) abort(); + obet=1+rnd(pocet); + for(i=0;obet>0;) + { + THUMAN *p; + i++; + if (i>=POCET_POSTAV) i=0; + p=&postavy[i]; + if (p->used && p->sektor==asect && p->lives) obet--; + } + h=&postavy[i]; + if (h->utek) + { + pocet=10; + h->utek--; + } + memcpy(vlastnosti,h->vlastnosti,sizeof(vlastnosti)); + spec=vlastnosti[VLS_KOUZLA]; + if (game_extras & EX_SHIELD_BLOCKING) PodporaStitu(h,vlastnosti); + else uprav_podle_kondice(h,&pocet); + h->dostal=vypocet_zasahu(p->vlastnosti,vlastnosti,pocet,0,0); //vypocet zasahu + if (h->dostal) p->dostal=0; + if (spec & SPL_OKO) //oko za oko pro hrace + { + vybrana_zbran=-1; + mob_hit(p,h->dostal); + mob_check_death(p-mobs,p); + } + if (h->dostal && p->vlastnosti[VLS_KOUZLA] & SPL_KNOCK) knock_player_back(h,p->dir); + if (p->vlastnosti[VLS_KOUZLA] & SPL_DRAIN) //energy drain pro potvoru + { + p->lives+=h->dostal; + if (p->lives>p->vlastnosti[VLS_MAXHIT])p->lives=p->vlastnosti[VLS_MAXHIT]; + } + dead=player_hit(h,h->dostal,1); + if (h->lives>h->vlastnosti[VLS_MAXHIT]) h->lives=h->vlastnosti[VLS_MAXHIT]; + if ((spec & SPL_TVAR) && (spec & SPL_OKO)) //nedovolena kombinace + { + char s[200]; + h->lives=0; + sprintf(s,texty[73+(postavy[i].female==1)],postavy[i].jmeno); + bott_disp_text(s); + rr=0; + dead=player_check_death(&postavy[i],0); + } + tt=add_to_timer(TM_CLEAR_ZASAHY,100,1,vymaz_zasahy);tt->userdata[0]=i;tt->userdata[1]=postavy[i].dostal; + if (dead && hlubina_level>0) + { + select_player=i; + vybrana_zbran=-1; + mob_hit(p,p->lives); //hlubina (potvora je mrtva); + } + bott_draw(rr); + } + } + + +void mobs_live(int num) + { + TMOB *p; + int xs,ys; + + p=&mobs[num]; + if (p->vlastnosti[VLS_KOUZLA] & SPL_STONED && p->lives>0) + { + p->vlajky &= ~MOB_IN_BATTLE; + return; + } + if (p->sector>=mapsize) + { + char buff[256]; + closemode(); + sprintf(buff,"Potvora v neexistujicim sektoru (%d, %d) ",num,p->sector); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONEXCLAMATION); + exit(1); + } + if (p->headx==p->locx && p->heady==p->locy && !p->anim_phase) + { + //zde se bude rozhodovat co dal; + p->anim_counter=-1; + stop_track_free(num+256); + if (battle) + { + if (p->mode!=MBA_NONE && p->mode!=MBA_FLEE) + { + neco_v_pohybu=1; + p->anim_phase=MOB_ATTACK; + p->anim_counter=0; + mob_sound_event(p,MBS_ATTACK); + mobs_live(num); + return; + } + if (p->mode==MBA_NONE) return; + rozhodni_o_smeru(p); + return; + } + if (p->stay_strategy & MOB_PICK) + { + if (!seber_predmet(p)) return; + if (pick_item_corpse(p,PK_PICK)) return; + p->stay_strategy&=~MOB_PICK; + } + if (p->stay_strategy & MOB_WALK) + { + if (p->walk_data>=224) + if (++p->walk_data<255) + { + p->anim_counter=-1; + return; + } + p->anim_counter=0; + rozhodni_o_smeru(p); + } + else + if (mob_map[p->sector]==num+MOB_START && (!p->next) ) + { + p->headx=128;p->heady=128; + } + } + else + { + if (p->anim_phasemode==MBA_FLEE) + { + int xr=abs(map_coord[p->sector].x-map_coord[viewsector].x); + int yr=abs(map_coord[p->sector].y-map_coord[viewsector].y); + if (xr>3 || yr>3) spd=100;else spd=2*p->speed; + } + else spd=p->speed; + xs=p->headx-p->locx; + ys=p->heady-p->locy; + if (!(game_extras & EX_WALKDIAGONAL) || p->stay_strategy & MOB_BIG) + { + if (ys!=0 && xs!=0) + if (p->dir==1 || p->dir==3) xs=0;else ys=0; + } + if (xs>spd) xs=spd; + else if (xs<-spd) xs=-spd; + if (ys>spd) ys=spd; + else if (ys<-spd) ys=-spd; + p->locx+=xs; + p->locy+=ys; + if (xs!=0 || ys!=0) neco_v_pohybu=1; + if (p->locx>192 || p->locx<64 || p->locy>192 || p->locy<64) mob_check(num,p); + } + p->anim_counter++; + if (p->anim_phase==MOB_ATTACK) + { + neco_v_pohybu=1; + if (p->anim_counter==p->hit_pos) mobs_hit(p); + if (p->anim_counter>=p->anim_counts[4]) + { + if (p->lives<1) p->anim_phase=MOB_TO_HIT;else p->anim_phase=0; + p->anim_counter=-1; + p->mode=MBA_NONE; + } + } + else + if (p->anim_phase==MOB_TO_HIT && p->anim_counter>=p->anim_counts[5]) + { + neco_v_pohybu=1; + p->anim_phase=0; + p->anim_counter=-1; + mob_check_death(num,p); + } + else + if (p->anim_phase==MOB_DEATH) + { + neco_v_pohybu=1; + if (p->anim_counter==2) mob_check_death(num,p); + else if (p->anim_counter>12) + { + p->anim_phase=0; + p->anim_counter=-1; + } + } + } + } + +void calc_mobs() + { + int i; + + neco_v_pohybu=0; + for(i=0;ivlajky & MOB_LIVE) + { + mob_test_na_bitvu(p); + if (p->vlajky & MOB_IN_BATTLE) b=1; + } + } + battle=b; + } + +void check_all_mobs_battle() //kontroluje zda je nekdo v battle + { + int i; + TMOB *p; + char b=0; + + for(i=0;ivlajky & MOB_LIVE) + if (p->vlajky & MOB_IN_BATTLE) + b=1; + } + battle=b; + } + + +#define Hi(x) ((x)>>16) +#define Lo(x) ((x)& 0xffff) + +int q_kolik_je_potvor(int sector) + { + if (mob_map[sector]) + if (mobs[mob_map[sector]-MOB_START].next) return 2; + else if (mobs[mob_map[sector]-MOB_START].stay_strategy & MOB_BIG) return 2; + else return 1; + return 0; + } + +void najdi_cestu(word start,word konec,int flag,word **cesta, int iamcnt) + { + longint *stack; + longint *stk_free; + longint *stk_cur; + char *ok_flags; + + *cesta=NULL; + stk_free=stk_cur=stack=getmem(4*(mapsize+2)); + memset(ok_flags=getmem((mapsize+8)/8),0,(mapsize+8)/8); + ok_flags[start>>3]|=1<<(start & 0x7); + for(*stk_free++=start;stk_free!=stk_cur;stk_cur++) + { + char i;word s,d=0xFFFF,ss; + s=(ss=Lo(*stk_cur))<<2; + for(i=0;i<4;i++) if (!(map_sides[s+i].flags & flag)) + { + char c; + word w; + d=map_sectors[ss].step_next[i]; + c=1<<(d & 0x7); + w=d>>3; + if (!(ok_flags[w] & c) && q_kolik_je_potvor(d)>3]|=1<<(start & 0x7); + for(*stk_free++=start;stk_free!=stk_cur;stk_cur++) + { + char i;word s,d,ss; + s=(ss=Lo(*stk_cur))<<2; + for(i=0;i<4;i++) if (!(map_sides[s+i].flags & SD_SOUND_IMPS)) + { + char c; + word w; + d=map_sectors[ss].step_next[i]; + c=1<<(d & 0x7); + w=d>>3; + if (!(ok_flags[w] & c)) + { + int mob; + + ok_flags[w]|=c; + *stk_free++=d | ((stk_cur-stack)<<16); + mob=mob_map[d]-MOB_START; + if (mob>=0) + { + reakce_na_hluk(mob,i+2&3); + if ((mob=mobs[mob].next-MOB_START)>=0) reakce_na_hluk(mob,i+2&3); + } + } + } + } + free(stack); + free(ok_flags); + } + +void refresh_mob_map() + { + int i,s; + + memset(mob_map,0,mapsize); + for(i=0;istay_strategy & MOB_BIG) return 0; + if (mm->dir!=i && i!=-1) return 0; + stop_mob(mm); + if (!mm->next && i==-1) + if (mm->headx==128 || mm->heady==128) smeruj_moba(mm,1); + i=mm->dir;m=mm->next; + } + if (!(map_sides[(sect<<2)+dir].flags & SD_THING_IMPS)) + sect=map_sectors[sect].step_next[dir]; + else return 1; + } + while (1); + } + + +//--------------------------------------------------------------------- +/* Nasledujici procedury a funkce se volaji pro chovani potvory v bitve */ + +static word last_sector; +static TMOB *fleeing_mob; + +static char valid_sectors(word sector) + { + int pp; + + last_sector=sector; + if (map_coord[sector].flags & MC_MARKED) return 0; //nevyhovujici + pp=q_kolik_je_potvor(sector); + if (pp==2) return 0; //moc potvor - nevyhovujici + if (fleeing_mob->stay_strategy & MOB_BIG && pp) return 0; + pp=map_sectors[sector].sector_type; + if (pp==S_DIRA || ISTELEPORT(pp)) return 0; + return 1; + } + + +char flee_monster_zac(TMOB *m) + { + int ss,s; + int i,j; + word *cesta,*c,cntr; + for(j=0;jsector,65535,SD_MONST_IMPS,valid_sectors,NULL); + i=labyrinth_find_path(m->sector,last_sector,SD_MONST_IMPS,valid_sectors,&cesta); + for(j=0;jmode=MBA_FLEE; + m->headx=m->locx+1; + m->actions=6; + m->dostal=0; + return 1; + } + +char akce_moba_zac(TMOB *m) + { + int sect,flg,i,j; + THUMAN *h; + char flee; + int perlives,dper,corlives; + + if (~m->vlajky & MOB_LIVE) return 1; + dper=m->dostal*100/(m->lives+m->dostal); + corlives=m->vlastnosti[VLS_MAXHIT]-m->flee_num*(m->vlastnosti[VLS_MAXHIT]-m->lives)/100; + perlives=(100-m->flee_num)*corlives*q_kolik_je_potvor(m->sector)/(m->vlastnosti[VLS_MAXHIT]); + perlives+=rnd(m->flee_num); + dper+=rnd(m->flee_num); + flee=dper>perlives || m->vlastnosti[VLS_KOUZLA] & SPL_FEAR; + if (flee) + { + if (flee_monster_zac(m)) return 1; + m->dostal=0; + } + if (call_mob_event(m->specproc,SMPR_ATTACK,m)) + { + mob_walk_sound(m); + return 0; + } + sect=map_sectors[m->sector].step_next[m->dir]; + flg=map_sides[(m->sector<<2)+m->dir].flags; + if (!(flg & SD_PLAY_IMPS)) + if (map_coord[sect].flags & MC_PLAYER) + for(i=0;iused && p->lives && p->sektor==sect) + { + if ((m->vlajky & MOB_CASTING && get_spell_track(m->casting))|| m->stay_strategy & MOB_ROGUE) + {stop_all_mobs_on_sector(m->sector);smeruj_moba(m,0);} + else stop_mob(m); + viewsector=sect; + viewdir=m->dir+2 &3; + m->csektor=sect; + if (m->vlajky & MOB_CASTING && rnd(100)<=m->vlastnosti[VLS_SMAGIE]) m->mode=MBA_SPELL;else m->mode=MBA_ATTACK; + bott_draw(1); + return 0; + } + } + for(i=0;i<4;i++) + { + sect=map_sectors[m->sector].step_next[i]; + flg=map_sides[(m->sector<<2)+i].flags; + if (!(flg & SD_MONST_IMPS)) + if (map_coord[sect].flags & MC_PLAYER) + for(j=0;jused && p->lives && p->sektor==sect && !(p->vlastnosti[VLS_KOUZLA] & SPL_INVIS)) + { + m->dir=i; + stop_mob(m); + return 1; + } + } + } + sect=m->sector; + i=q_vidis_postavu(m->sector,m->dir,m,&j,1); + h=postavy+i; + if (i>-1) + if (((m->vlajky & MOB_CASTING && get_spell_track(m->casting))|| m->stay_strategy & MOB_ROGUE) && + (map_coord[m->sector].x==map_coord[h->sektor].x || map_coord[m->sector].y==map_coord[h->sektor].y) + && track_mob(m->sector,m->dir)) + { + m->dir=j; + stop_all_mobs_on_sector(m->sector); + if (~m->stay_strategy & MOB_ROGUE) + m->mode=MBA_SPELL; + else + m->mode=MBA_ATTACK; + smeruj_moba(m,0); + viewsector=h->sektor; + viewdir=m->dir+2 & 3; + return 0; + } + else + { + word *cesta; + + najdi_cestu(m->sector,postavy[i].sektor,SD_MONST_IMPS,&cesta,(m->stay_strategy & MOB_BIG)?1:2); + if (cesta!=NULL) + { + for(j=0;j<4 && map_sectors[sect].step_next[j]!=cesta[0];j++); + m->dir=j & 3; + free(cesta); + if (m->dir & 1)m->headx=mob_go_x[m->dir];else m->heady=mob_go_y[m->dir]; + mob_sound_event(m,MBS_WALK); + return 1; + } + else + return 1; + } + rozhodni_o_smeru(m); + if (m->dir & 1)m->headx=mob_go_x[m->dir];else m->heady=mob_go_y[m->dir]; +// m->headx=mob_go_x[m->dir]; +// m->heady=mob_go_y[m->dir]; + m->vlajky&=~MOB_IN_BATTLE; + return 1; + } + +void mob_animuj() + { + int mob; + + for(mob=0;moblocylocy) return m;else if (m1->locy>m2->locy) return ch;break; + case 1: if (m1->locxlocx) return m;else if (m1->locx>m2->locx) return ch;break; + case 0: if (m1->locy>m2->locy) return m;else if (m1->locylocy) return ch;break; + case 3: if (m1->locx>m2->locx) return m;else if (m1->locxlocx) return ch;break; + } + x=rnd(2); + if (x) return ch; + return m; + } + +static void knock_mob_back(TMOB *mm,int dir) + { + char chk; + int i,sek,mnum,mms; + + if (call_mob_event(mm->specproc,SMPR_KNOCK,mm)) return; + mms=mm->sector;mnum=mm-mobs+MOB_START; + chk=mob_check_next_sector(mms,dir,mm->stay_strategy,mm->vlajky); + if (chk) return; + sek=map_sectors[mms].step_next[dir]; + i=mob_map[sek]; + if (mob_map[mms]!=mnum) mobs[mob_map[mms]-MOB_START].next=0;else mob_map[mms]=mm->next; + if (i) + { + mm->next=i; + uhni_mobe(1,i-1,0); + } + else mm->next=0; + mob_map[sek]=mm-mobs+MOB_START;mm->sector=sek; + recheck_button(mms,1); + recheck_button(sek,1); + } + +int utok_na_sektor(THUMAN *p,TMOB *mm,int ch,int bonus) + { + int dostal; + + dostal=vypocet_zasahu(p->vlastnosti,mm->vlastnosti,ch,bonus,0); + mob_hit(mm,dostal); + if (dostal && p->vlastnosti[VLS_KOUZLA] & SPL_KNOCK) knock_mob_back(mm,p->direction); + if (mm->vlastnosti[VLS_KOUZLA] & SPL_OKO) //oko za oko pro potvoru + { + p->lives-=dostal; + player_check_death(p,0); + } + if (dostal) + { + mm->dir=(p->direction+2)&3; + play_sample_at_sector(H_SND_SWHIT1+rnd(2),viewsector,viewsector,0,0); + if (p->vlastnosti[VLS_KOUZLA] & SPL_DRAIN) + { + p->lives+=dostal*8/(rnd(16)+16); + if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; + } + } + else + { + ddostal=0; + play_sample_at_sector(H_SND_SWMISS1+rnd(2),viewsector,viewsector,0,0); + } + mm->vlajky|=MOB_IN_BATTLE; + neco_v_pohybu=1; + return ddostal; + } + +void sleep_enemy(char regen) + { + int i; + + for(i=0;ivlajky & MOB_LIVE && m->lives>0) + { + if (regen) + { + m->lives+=m->vlastnosti[VLS_HPREG]; + if (m->lives>m->vlastnosti[VLS_MAXHIT]) m->lives=m->vlastnosti[VLS_MAXHIT]; + } + if (m->stay_strategy & MOB_WALK) + { + m->locx=m->headx; + m->locy=m->heady; + mob_check(i,m); + if (m->locx<64 || m->locx>192) m->locx=128; + if (m->locy<64 || m->locy>192) m->locy=128; + if (m->locx==m->headx && m->locy==m->heady) rozhodni_o_smeru(m); + } + } + + } + } + +static int mob_mob_alter(int num) + { + int i; + num-=MOB_START; + if (num<0) return 0xff; + if (mobs[num].dialog>-1 && ~mobs[num].vlajky & MOB_PASSABLE) start_dialog(mobs[num].dialog,num); + else if (mobs[num].stay_strategy & MOB_WATCH) + { + stop_mob(mobs+num); + if (!battle) battle=1; + } + i=mob_mob_alter(mobs[num].next); + return (mobs[num].vlajky & MOB_PASSABLE) & i; + } + +int mob_alter(int sect) + { + char p; + att_player=0xff; + p=mob_mob_alter(mob_map[sect]); +/* if (p) + { + int i;THUMAN *h; + for (i=0;iused && h->lives && h->groupnum==cur_group) + {att_player=group_sort[i];break;} + } + }*/ + return p; + } + +void regen_all_mobs() + { + int i; + TMOB *m; + + for(i=0,m=mobs;ivlajky & MOB_LIVE && m->vlastnosti[VLS_HPREG]) + m->lives=m->vlastnosti[VLS_MAXHIT]; + } + diff --git a/GAME/ENGINE1.C b/GAME/ENGINE1.C new file mode 100644 index 0000000..2b06abd --- /dev/null +++ b/GAME/ENGINE1.C @@ -0,0 +1,1412 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "math.h" +#include "globals.h" +#include "engine1.h" + +#define CTVR 128 + +t_points points; +struct all_view showtabs; +static char backgrnd_mode=0; + +static int lclip,rclip; + +ZOOMINFO zoom; +char zooming_xtable[ZOOM_PHASES][VIEW_SIZE_X]; +short zooming_ytable[ZOOM_PHASES][VIEW_SIZE_Y]; +short zooming_points[ZOOM_PHASES][4] + ={ + {620,349,10,3}, + {600,338,20,7}, + {580,327,30,11}, + {560,316,40,14}, + {540,305,50,18}, + {520,293,60,21}, + {500,282,70,25}, + {480,271,80,28}, + {460,259,90,31} + }; +int zooming_step=1; +int rot_phases=1; +int yreq; +int last_scale; +char secnd_shade=1; + +void sikma_zleva(void); +//#pragma aux sikma_zleva parm modify [EAX EBX ECX EDX ESI EDI] +void sikma_zprava(void); +//#pragma aux sikma_zprava parm modify [EAX EBX ECX EDX ESI EDI] +/*void zooming_dx(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming_dx parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void zooming32(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming32 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void zooming32b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming32b parm [ESI][EDI][EAX][EBX][ECX] modify [EAX EDX] +void zooming_lo(void *source,void *target,void *xlat,long xysize); +//#pragma aux zooming_lo parm [ESI][EDI][EBX][ECX] modify [EAX EDX] +void zooming256(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming256 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void zooming256b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming256b parm [ESI][EDI][EAX][EBX][ECX] modify [EAX EDX] +void zooming64(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming64 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void zooming64b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux zooming64b parm [ESI][EDI][EAX][EBX][ECX] modify [EAX EDX] +void scroll_support_dx(void *lbuf,void *src1,void *src2,int size1); +//#pragma aux scroll_support_dx parm [EDI][ESI][EDX][ECX] modify [EAX] +void scroll_support_32(void *lbuf,void *src1,void *src2,int size1); +//#pragma aux scroll_support_32 parm [EDI][ESI][EDX][ECX] modify [EAX] +void scroll_support_32b(void *lbuf,void *src1,void *src2,int size1); +//#pragma aux scroll_support_32b parm [EDI][ESI][EDX][ECX] modify [EAX] +void scroll_support_256(void *lbuf,void *src1,void *src2,int size1,void *xlat); +//#pragma aux scroll_support_256 parm [EDI][ESI][EDX][ECX][EBX] modify [EAX]; +void scroll_support_256b(void *lbuf,void *src1,void *src2,int size1,void *xlat); +//#pragma aux scroll_support_256b parm [EDI][ESI][EDX][ECX][EBX] modify [EAX]; +void scroll_support_64(void *lbuf,void *src1,void *src2,int size1,void *xlat); +//#pragma aux scroll_support_64 parm [EDI][ESI][EDX][ECX][EBX] modify [EAX]; +void scroll_support_64b(void *lbuf,void *src1,void *src2,int size1,void *xlat); +//#pragma aux scroll_support_64b parm [EDI][ESI][EDX][ECX][EBX] modify [EAX];*/ +void fcdraw(void *source,void *target, void *table); +//#pragma aux fcdraw parm [EDX][EBX][EAX] modify [ECX ESI EDI]; + +/*void lodka32(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka32 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void lodka_dx(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka_dx parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void lodka32b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka32b parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] + +void lodka256(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka256 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void lodka256b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka256b parm [ESI][EDI][EAX][EBX][ECX] modify [EAX EDX] + +void lodka64(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka64 parm [ESI][EDI][EAX][EBX][ECX] modify [EDX] +void lodka64b(void *source,void *target,void *background,void *xlat,long xysize); +//#pragma aux lodka64b parm [ESI][EDI][EAX][EBX][ECX] modify [EAX EDX] +*/ + +void *p,*p2,*pozadi,*podlaha,*strop,*sit;int i; +void (*zooming)(void *source,long target,word *background,void *xlat,long xysize); +void (*turn)(long lbuf,void *src1,void *src2,int size1); +word *GetBuffer2nd(); +word *background; +char debug=0,nosides=0,nofloors=0,drwsit=0,show_names=0,show_lives=0; +static long old_timer; + +static void wait_timer() + { + Sleep(10); + } + +/*void zooming1(void *source,long target,word *background,void *xlat,long xysize) + { + wait_timer(); + if (backgrnd_mode) + lodka_dx(source,GetScreenAdr()+target,background+3,xlat,xysize); + else + zooming_dx(source,GetScreenAdr()+target,background+3,xlat,xysize); + showview(0,0,0,0); + } +/* +void zooming2(void *source,long target,word *background,void *xlat,long xysize) + { + word *lbuffer=LockDirectScreen(); + wait_timer(); + if (backgrnd_mode) + lodka256(source,lbuffer+(target>>1),background+3,xlat,xysize); + else + zooming256(source,lbuffer+(target>>1),background+3,xlat,xysize); + UnlockDirectScreen(); + } + +void zooming3(void *source,long target,word *background,void *xlat,long xysize) + { + source;target;background;xlat;xysize; + } + +/*void zooming4(void *source,long target,word *background,void *xlat,long xysize) + { + word *lbuffer=LockDirectScreen(); + wait_timer(); + if (backgrnd_mode) + lodka32b(source,(void *)(target*2),background+3,xlat,xysize); + else + zooming32b(source,(void *)(target*2),background+3,xlat,xysize); + UnlockDirectScreen(); + }*/ +/* +void zooming5(void *source,long target,word *background,void *xlat,long xysize) + { + wait_timer(); + if (backgrnd_mode) + lodka256b(source,(void *)target,background+3,xlat,xysize); + else + zooming256b(source,(void *)target,background+3,xlat,xysize); + } + +void zooming6(void *source,long target,word *background,void *xlat,long xysize) + { + word *lbuffer=LockDirectScreen(); + wait_timer(); + if (backgrnd_mode) + lodka_dx(source,lbuffer+(target),background+3,xlat,xysize); + else + zooming_dx(source,lbuffer+(target),background+3,xlat,xysize); + UnlockDirectScreen(); + } +/* +void zooming7(void *source,long target,word *background,void *xlat,long xysize) + { + wait_timer(); + if (backgrnd_mode) + lodka64b(source,(void *)(target*2),background+3,xlat,xysize); + else + zooming64b(source,(void *)(target*2),background+3,xlat,xysize); + } +*/ + +void turn1(long lbuf,void *src1,void *src2,int size1) + { +//wait_timer(); +// scroll_support_dx(lbuf+GetScreenAdr(),src1,src2,size1); + showview(0,0,0,0); + } + +/*void turn2(long lbuf,void *src1,void *src2,int size1) + { + wait_timer(); + scroll_support_256((lbuf>>1)+lbuffer,src1,src2,size1,xlatmem); + } +*/ +void turn3(long lbuf,void *src1,void *src2,int size1) + { + lbuf;src1;src2;size1; + } +/* +void turn4(long lbuf,void *src1,void *src2,int size1) + { + wait_timer(); + scroll_support_32b((void *)(lbuf*2),src1,src2,size1); + } + +void turn5(long lbuf,void *src1,void *src2,int size1) + { + wait_timer(); + scroll_support_256b((void *)lbuf,src1,src2,size1,xlatmem); + } +*/ +/* +void turn6(long lbuf,void *src1,void *src2,int size1) + { + word *lbuffer=LockDirectScreen(); + wait_timer(); + scroll_support_dx((lbuf)+lbuffer,src1,src2,size1,xlatmem); + UnlockDirectScreen(); + } +/* +void turn7(long lbuf,void *src1,void *src2,int size1) + { + wait_timer(); + scroll_support_64b((void *)(lbuf*2),src1,src2,size1,xlatmem); + } +*/ + + +void calc_points(void) + { + int i,j,x1,y1,x2,y2; + + for (j=0;jtxt_size_x) + { + if (z==-1) z=i-3; + j=((i-z)*txt_size_x)/scale1+txt_size_x; + } + else j=(i*txt_size_x)/len; + *ptr++=(j-old-1); + old=j; + } + + } + +void calc_y_buffer(short *ptr,long txt_size_y, long len,long total) + { + int i,j,old; + + old=-1; + for (i=0;iMIDDLE_X) showtabs.z_table[x][y].used=0; + else + { + showtabs.z_table[x][y].used=1; + rozdil1=points[x][0][y].x-points[x][0][y+1].x; + rozdil2=rozdil1-MIDDLE_X+points[x][0][y+1].x; + rozdil3=points[0][0][y].x-points[0][0][y+1].x; + if (rozdil2<0) + { + showtabs.z_table[x][y].xpos=MIDDLE_X-points[x][0][y].x; + showtabs.z_table[x][y].txtoffset=0; + } + else + { + showtabs.z_table[x][y].xpos=MIDDLE_X-points[x][0][y].x; + showtabs.z_table[x][y].txtoffset=(TXT_SIZE_X_3D*rozdil2/rozdil1); + } + showtabs.z_table[x][y].point_total=rozdil1; + calc_x_buffer(showtabs.z_table[x][y].zoom_table,TXT_SIZE_X_3D,rozdil1,VIEW_SIZE_X,rozdil3); + } + + } + + for (y=0;yTXT_SIZE_X) showtabs.z_table[x][y].used=0; + else + { + showtabs.x_table[x][y].used=1; + rozdil1=points[1][0][y+1].x-points[0][0][y+1].x; + rozdil2=-MIDDLE_X+points[x][0][y+1].x; + if (rozdil2<0) + { + showtabs.x_table[x][y].xpos=MIDDLE_X-points[x][0][y+1].x; + showtabs.x_table[x][y].txtoffset=0; + showtabs.x_table[x][y].max_x=rozdil1; + } + else + { + showtabs.x_table[x][y].xpos=MIDDLE_X-points[x][0][y+1].x; + showtabs.x_table[x][y].txtoffset=(TXT_SIZE_X*rozdil2/rozdil1); + showtabs.x_table[x][y].max_x=MIDDLE_X-points[x-1][0][y+1].x; + } + if (x!=0)showtabs.x_table[x][y].xpos2=VIEW_SIZE_X-(showtabs.x_table[x][y].xpos+rozdil1); + showtabs.x_table[x][y].point_total=rozdil1; + calc_x_buffer(showtabs.x_table[x][y].zoom_table,TXT_SIZE_X,rozdil1,VIEW_SIZE_X,rozdil1); + } + + } + + for(x=0;x>1; + y1=(VIEW_SIZE_Y-y)-MIDDLE_Y; + yp=1;while (points[0][0][yp].y>y1) yp++; + if (xstrd) + { + xl=+points[x-strd-1][0][0].x;xr=+points[x-strd][0][0].x; + } + y1=(VIEW_SIZE_Y-y)-MIDDLE_Y; + xl=xl*(y1+1)/points[0][0][0].y+MIDDLE_X; + xr=xr*(y1+1)/points[0][0][0].y+MIDDLE_X; + if (xl<0) xl=0;if (xr<0) xr=0; + if (xl>639) xl=639;if (xr>639) xr=639; + showtabs.f_table[x][y].lineofs=(y1+MIDDLE_Y)*scr_linelen+xl*2; + showtabs.f_table[x][y].linesize=xr-xl+(xl!=xr); + showtabs.f_table[x][y].counter=(y1-points[0][0][yp].y); + showtabs.f_table[x][y].txtrofs=(y1+MIDDLE_Y-VIEW_SIZE_Y+F_YMAP_SIZE)*1280+xl*2; + } + + for(x=0;x>1; + y1=y-MIDDLE_Y; + yp=1;while (points[0][1][yp].ystrd) + { + xl=+points[x-strd-1][1][0].x;xr=+points[x-strd][1][0].x; + } + xl=xl*(y1-2)/points[0][1][0].y+MIDDLE_X; + xr=xr*(y1-2)/points[0][1][0].y+MIDDLE_X; + if (xl<0) xl=0;if (xr<0) xr=0; + if (xl>639) xl=639;if (xr>639) xr=639; + showtabs.c_table[x][y].lineofs=(y1+MIDDLE_Y)*scr_linelen+xl*2; + showtabs.c_table[x][y].linesize=xr-xl+(xl!=xr); + showtabs.c_table[x][y].counter=points[0][1][yp].y-y1; + showtabs.c_table[x][y].txtrofs=(y1+MIDDLE_Y)*1280+xl*2; + } + + + } + +void calc_zooming(char *buffer,int dvojice,int oldsiz) + { + int poz,roz,i,x; + + poz=-2; + for(i=0;i2) roz=2; + if (roz<1) roz=1; + if (roz==1) *buffer++=1; else *buffer++=0; + poz+=roz; + } + } + +void create_zooming(void) + { + int i,j; + + for (j=0;j=0;i-=zooming_step) + { + zoom.xtable=(long *)&zooming_xtable[i]; + zoom.ytable=(short *)&zooming_ytable[i]; + zoom.texture_line=0; + do_events(); + zooming(GetScreenAdr()+zooming_points[i][2]+zooming_points[i][3]*scr_linelen2+SCREEN_OFFSET,SCREEN_OFFSET,background,xlatmem,(360<<16)+320); + } + } + +*/ + +static void turn_left_right(char right) + { + { + if (!rot_phases) return; + { + long tmp=get_timer_value(); + void *buffer=DxPrepareTurn(SCREEN_OFFLINE); + + int maxtime=5*rot_phases; + int curtime; + float phase; + int last=90; + + do + { + curtime=get_timer_value()-tmp; + phase=(curtime)*(1.0f/(float)maxtime); + //phase=(float)sin(3.14159265*0.5f*phase); + DxTurn(buffer,right,SCREEN_OFFLINE,90,phase,NULL); + do_events(); + } + while (curtime>5; + rev&=3; + if (celx<=0) x3d=&showtabs.z_table[-celx][cely]; else x3d=&showtabs.z_table[celx][cely]; + x0d=&showtabs.z_table[0][cely]; + if (!x3d->used) return; + yd=&showtabs.y_table[cely]; + yp=&showtabs.y_table[cely+1]; + txtsx=*(word *)stena; + txtsy=*((word *)stena+1); + if (rev<2) + { + xofs-=(txtsx>>1)*TXT_SIZE_X/TXT_SIZE_X_3D;yofs-=txtsy>>1; + } + rev&=1; + yss=(points[0][0][cely].y-points[0][0][cely+1].y)*xofs/TXT_SIZE_X; + ysd=(points[0][1][cely].y-points[0][1][cely+1].y)*xofs/TXT_SIZE_X; + yofs=yofs*(yd->vert_size-yss+ysd)/TXT_SIZE_Y+yss; + xofs=xofs*x3d->point_total/TXT_SIZE_X; + if (txtsx>x3d->point_total && celx) + { + realsx=txtsx*x0d->point_total/TXT_SIZE_X_3D; + realsx+=x3d->point_total-x0d->point_total; + } + else realsx=txtsx*x3d->point_total/TXT_SIZE_X_3D; + realsy=txtsy*yd->vert_size/TXT_SIZE_Y-1; + x=x3d->xpos+xofs; + if (-x>realsx) return; + p=stena;p+=SHADE_PAL+2*2+2; + i=0; + while (x<0) + { + p+=x3d->zoom_table[i++]+1; + realsx--;x++; + } + if (x+realsx>640) realsx=640-x; + if (realsx<=0) return; + yofs=yd->drawline-yofs; + yofs+=(plac==1)?(-yp->vert_size+points[0][0][cely+1].y-points[0][0][cely].y):((plac==2)?(yd->vert_size):0); + if (yofs>360) + { + int r=yofs-360,ui; + if (r>realsy) return; + ui=(r*txtsy/realsy); + p+=txtsx*ui;realsy-=r; + yofs=360; + } + if (yofs-realsy<0) realsy=yofs; + if (rev) + zoom.startptr=GetBuffer2nd()+yofs*scr_linelen2+(639-x)+SCREEN_OFFSET; + else + zoom.startptr=GetBuffer2nd()+yofs*scr_linelen2+x+SCREEN_OFFSET; + zoom.texture=p; + zoom.texture_line=txtsx; + zoom.xtable=&x3d->zoom_table[i]; + zoom.ytable=yd->zoom_table; + zoom.palette=(word *)((byte *)stena+6+512*(cely)+(secnd_shade?SHADE_STEPS*512:0)); + zoom.ycount=realsy+1; + zoom.xmax=realsx; + zoom.line_len=scr_linelen; + __try + { + if (rev) sikma_zprava(); else sikma_zleva(); + } + __finally + { + } + } + + +void show_cel2(int celx,int cely,void *stena,int xofs,int yofs,char rev) + { + T_INFO_X *x3d; + T_INFO_Y *yd; + int txtsx,txtsy,realsx,realsy,x,i; + char *p;int plac; + + if (stena==NULL) return ; + plac=rev>>5; + rev&=3; + if (celx==2) + x=celx; + if (rev==2) celx=-celx; + if (celx<=0) x3d=&showtabs.x_table[-celx][cely]; else x3d=&showtabs.x_table[celx][cely]; + if (!x3d->used) return; + yd=&showtabs.y_table[cely+1]; + txtsx=*(word *)stena; + txtsy=*((word *)stena+1); + if (!rev) + { + xofs-=txtsx>>1;yofs-=txtsy>>1; + } + yofs=yofs*yd->vert_size/TXT_SIZE_Y; + xofs=xofs*x3d->point_total/TXT_SIZE_X; + realsx=txtsx*x3d->point_total/TXT_SIZE_X; + realsy=txtsy*yd->vert_size/TXT_SIZE_Y; + if (celx<=0) x=x3d->xpos+xofs; else x=x3d->xpos2+xofs; + if (-x>realsx) return; + p=stena;p+=SHADE_PAL+2*2+2; + i=0; + while (x<0) + { + p+=x3d->zoom_table[i++]+1; + realsx--;x++; + } + if (x+realsx>640) realsx=640-x; + if (realsx<=0) return; + yofs=yd->drawline-yofs; + yofs+=(plac==1)?(-yd->vert_size):((plac==2)?(yd->vert_size):0); + if (yofs>360) + { + int r=yofs-360,ui; + if (r>realsy) return; + ui=(r*txtsy/realsy);realsy-=r; + p+=txtsx*ui; + yofs=360; + } + if (yofs-realsy<0) realsy=yofs; + if (rev==2) + zoom.startptr=GetBuffer2nd()+(yofs)*scr_linelen2+(639-x)+SCREEN_OFFSET; + else + zoom.startptr=GetBuffer2nd()+(yofs)*scr_linelen2+x+SCREEN_OFFSET; + zoom.texture=p; + zoom.texture_line=txtsx; + zoom.xtable=x3d->zoom_table; + zoom.ytable=yd->zoom_table; + zoom.palette=(word *)((byte *)stena+6+512*(cely)+(secnd_shade?SHADE_STEPS*512:0)); + zoom.ycount=realsy+1; + zoom.xmax=realsx; + zoom.line_len=scr_linelen; + if (rev==2) sikma_zprava(); else sikma_zleva(); + } + + + +void draw_floor_ceil(int celx,int cely,char f_c,void *txtr) + { + int y; + + if (nofloors) return; + txtr=(void *)((word *)txtr+3); + if (f_c==0) //podlaha + { + y=(VIEW_SIZE_Y-MIDDLE_Y)-points[0][0][cely].y+1; + if (y<1) y=1; + txtr=(void *)((word *)txtr); + fcdraw(txtr,GetBuffer2nd()+SCREEN_OFFSET,&showtabs.f_table[celx+3][y]); +/* if (debug) + { + memcpy(GetScreenAdr(),GetBuffer2nd(),512000); + showview(0,0,0,0); + }*/ + } + else + { + y=points[0][1][cely].y+MIDDLE_Y+1; + if (y<0) y=0; + fcdraw(txtr,GetBuffer2nd()+SCREEN_OFFSET,&showtabs.c_table[celx+3][y]); +/* if (debug) + { + memcpy(GetScreenAdr(),GetBuffer2nd(),512000); + showview(0,0,0,0); + }*/ + } + + } + + +void OutBuffer2nd(void) + { + int i; + for (i=0;i<480;i++) + memcpy(GetScreenAdr()+i*scr_linelen2,GetBuffer2nd()+i*scr_linelen2,640*2); + } + +void CopyBuffer2nd(void) + { + int i; + for (i=0;i<480;i++) + memcpy(GetBuffer2nd()+i*scr_linelen2,GetScreenAdr()+i*scr_linelen2,640*2); + } + + /*void chozeni(void) + { + char c; char dir=0;word sector=22; + + zooming_forward(); + swap_buffs(); + showview(0,0,0,0); + do + { + while (_bios_keybrd(_KEYBRD_READY)) _bios_keybrd(_KEYBRD_READ); + c=_bios_keybrd(_KEYBRD_READ) >> 8; + switch (c) + { + case 'H':if (mapa[sector][dir]!=-1) + { + sector=mapa[sector][dir]; + render_scene(sector,dir); + if (!debug) zooming_forward(); + swap_buffs(); + showview(0,0,0,0); + }break; + case 'P':if (mapa[sector][(dir+2)&3]!=-1) + { + sector=mapa[sector][(dir+2)&3]; + render_scene(sector,dir); + swap_buffs(); + if (!debug) zooming_backward(); + showview(0,0,0,0); + }break; + case 'M':dir=(dir+1)&3; + render_scene(sector,dir); + if (!debug) turn_left(); + swap_buffs(); + showview(0,0,0,0); + break; + case 'K':dir=(dir-1)&3; + render_scene(sector,dir); + swap_buffs(); + if (!debug) turn_right(); + showview(0,0,0,0); + break; + case ';':debug=!debug;break; + case '<':nosides=!nosides;break; + case '=':nofloors=!nofloors;break; + case '>':drwsit=!drwsit;break; + } + } + while (c!=1); + } +*/ +/*void ask_video(video) + { + char c,ok,er; + printf("\nJaky videomode?:\n" + " 1) 640x480x256 Pomale pocitace\n" + " 2) 640x480xHiColor Pomale pocitace\n" + " 3) 640x480x256 Rychle pocitace\n" + " 4) 640x480xHiColor Rychle pocitace\n"); + screen_buffer_size=640*480*2; + do + { + if (!video) c=_bios_keybrd(_KEYBRD_READ)>>8;else c=video+1; + ok=1;er=0; + line480=1; + switch (c) + { + case 1:exit(0); + case 4:line480=1;er=initmode256(load_file("xlat256.pal")); + zooming=zooming2;ok=0; + turn=turn2; + if (banking) + { + turn=turn5; + zooming=zooming5; + } + break; + case 5:line480=1;er=initmode32(); + zooming=zooming1;ok=0; + turn=turn1; + if (banking) + { + turn=turn4; + zooming=zooming4; + } + break; + case 2:line480=1;er=initmode256(load_file("xlat256.pal")); + zooming=zooming2;ok=0;zooming_step=2;rot_phases=2;rot_step=140; + turn=turn2; + if (banking) + { + turn=turn5; + zooming=zooming5; + } + break; + case 3:line480=1;er=initmode32(); + zooming=zooming1;ok=0;zooming_step=2;rot_phases=2;rot_step=140; + turn=turn1; + if (banking) + { + turn=turn4; + zooming=zooming4; + } + break; + } + if (er) + { + ok=1; + if (er==-1) + printf("Rezim zrejme neni podporovan. Zkuste nainstalovat univbe\n"); + else + printf("Graficka karta asi nepodporuje Linear Frame Buffer. \n" + "Pokud tomu tak neni, zkontrolujte zda neni vypnuty.\n"); + } + } + while (ok); + } + + */ +void report_mode(int mode) + { +/* switch (mode) + { + case 1:zooming=zooming1; turn=turn1;break; + case 2:STOP();break; + case 3:STOP();break; + case 4:STOP();break; + case 5:STOP();break; + case 6:STOP();break; + case 7:STOP();break; + }*/ + } + +__inline void clear_color(void *start,int _size,word _color) + { + word *s = (word *)start; + int i; + for (i = 0; i < _size; i++) s[i] = _color; +/* __asm + { + mov edi,start + mov ecx,_size + movzx eax,_color + mov ebx,eax + shl eax,16 + mov ax,bx + shr ecx,1 + rep stosd + rcl ecx,1 + rep stosw + }*/ + } + + //parm [EDI][ECX][EAX] modify [EBX]; + + +void clear_buff(word *background,word backcolor,int lines) +{ + if (background!=NULL) put_picture(0,SCREEN_OFFLINE,background);else lines=0; + if (lines!=360) + for (i=lines;i<360;i++) + clear_color(GetBuffer2nd()+SCREEN_OFFSET+scr_linelen2*i,640,backcolor); + +} + +void clear_screen(word *screen, word color) +{ +for (i=0;i<480;i++) clear_color(screen+scr_linelen2*i,640,color); +} + +void general_engine_init() + { + calc_points(); + create_tables(); + create_zooming(); + clear_screen(GetScreenAdr(),0); + clear_screen(GetBuffer2nd(),0); + screen_buffer_size=scr_linelen2*480*2; +} + +void map_pos(int celx,int cely,int posx,int posy,int posz,int *x,int *y) + { + char negate2=0; + int xl,xr; + int p1,p2,p; + if (celx<0) + { + negate2=1; + posx=CTVR-posx; + celx=-celx; + } + p1=(points[0][0][cely].y-points[0][1][cely].y); + p2=(points[0][0][cely+1].y-points[0][1][cely+1].y); + last_scale=p=posy*(p2-p1)/CTVR+p1; + *y=points[0][0][cely].y-(posy*(points[0][0][cely].y-points[0][0][cely+1].y)/CTVR)-p*posz/CTVR; + xr=points[celx][0][cely].x-(posy*(points[celx][0][cely].x-points[celx][0][cely+1].x)/CTVR); + if (celx) xl=points[celx-1][0][cely].x-(posy*(points[celx-1][0][cely].x-points[celx-1][0][cely+1].x)/CTVR); + else xl=-xr; + *x=xl+((xr-xl)*posx/CTVR); + if (negate2) *x=-*x; + *x+=MIDDLE_X; + *y+=MIDDLE_Y; + } + +/*void draw_item(int celx,int cely,int posx,int posy,short *pic,int index) + { + int x,y; + int xs,ys,xsr,ysr,xofs,xmax; + T_INFO_Y *yd; + T_INFO_X *x3d; + int ys1,ys2,xs1,xs2; + static long zoomtab_x[640]; + static short zoomtab_y[360]; + static lastcely=-1; + int randx,randy; + static int indextab[][2]={{0,0},{0,10},{1,0},{-1,0},{1,10},{-1,10},{-2,10},{2,10}}; + + if (pic==NULL) return; + if (!cely && !posy) return; + if (cely==VIEW3D_Z-1 && posy) return; + x3d=&showtabs.x_table[abs(celx)]; + if (!x3d[cely].used || !x3d[1].used ) return; + randx=indextab[index & 0x7][0]; + randy=indextab[index & 0x7][1]; + map_pos(celx,cely,64*posx+32+randx,64*posy+randy,0,&x,&y); + yd=&showtabs.y_table; + ys2=yd[1].vert_size; + xs2=x3d[1].point_total; + if (posy) + { + xs1=(x3d[cely].point_total+x3d[cely+1].point_total)>>1; + ys1=(yd[cely].vert_size+yd[cely+1].vert_size)>>1; + } + else + { + xs1=x3d[cely].point_total; + ys1=yd[cely].vert_size; + } + xs=pic[0]; + ys=pic[1]; + xsr=xs*ys1/ys2; + ysr=ys*xs1/xs2; + x-=xsr>>1; + //y+=ysr>>1; + if (-x>=xsr || x>VIEW_SIZE_X) return; + if (x<0) + { + xofs=-x*xs/xsr; + xmax=xsr+x; + x=0; + } + else if (x+xsr>VIEW_SIZE_X) + { + xofs=0; + xmax=VIEW_SIZE_X-x; + } + else + { + xofs=0; + xmax=xsr; + } + if ((cely<<1)+posy!=lastcely) + { + lastcely=(cely<<1)+posy; + calc_x_buffer((long *)&zoomtab_x,xs2,xs1,640,xs2); + calc_y_buffer((short *)&zoomtab_y,ys2,ys1,360); + } + if (y-ysr<0) ysr=y; + zoom.startptr=GetBuffer2nd()+y*640+x+SCREEN_OFFSET; + zoom.texture=(short *)((char *)(&pic[3+SHADE_PAL])+xofs); + zoom.texture_line=xs; + zoom.xtable=(long *)&zoomtab_x; + zoom.ytable=(short *)&zoomtab_y; + zoom.palette=(word *)&pic[3+cely*256+(secnd_shade?SHADE_STEPS*256:0)]; + zoom.ycount=ysr; + zoom.xmax=xmax; + zoom.line_len=1280; + sikma_zleva(); + } +*/ + +static int items_indextab[][2]={{0,0},{-1,3},{1,7},{-1,7},{1,10},{-1,10},{0,10},{-2,15}}; +void draw_item(int celx,int cely,int posx,int posy,short *txtr,int index) + { + int x,y; + int clipl,clipr; + int randx,randy; + + if (txtr==NULL) return; + randx=items_indextab[7-(index & 0x7)][0]; + randy=items_indextab[7-(index & 0x7)][1]; + map_pos(celx,cely,42*posx+42+randx,72*posy+randy,0,&x,&y); + x-=(txtr[0]/2*last_scale)/320; + if (x<0) + { + clipl=-x; + x=0; + } + else clipl=0; + clipr=640-x; + if (clipr>0) + enemy_draw(txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,6+512*cely+(secnd_shade?SHADE_STEPS*512:0),last_scale,y,(clipr<<16)+clipl); + } + + +void put_textured_bar(void *src,int x,int y,int xs,int ys,int xofs,int yofs) + { + word *pos; + word *xy; + + pos=GetScreenAdr()+x+scr_linelen2*y; + xy=src; + xofs=xofs%xy[0]; + yofs=yofs%xy[1]; + if (xofs<0) xofs+=xy[0]; + if (yofs<0) yofs+=xy[1]; + put_textured_bar_(src,pos,xs,ys,xofs,yofs); + } + +void draw_placed_texture(short *txtr,int celx,int cely,int posx,int posy,int posz,char turn) + { + int x,y; + int clipl,clipr; + + if (txtr==NULL) return; + map_pos(celx,cely,posx,posy,posz,&x,&y); + x-=(txtr[0]/2*last_scale)/320; + y+=(txtr[1]/2*last_scale)/320; + if (y>400) y=400; + if (x<0) + { + clipl=-x; + x=0; + } + else clipl=0; + clipr=640-x; + if (clipr>0) + if (turn) enemy_draw_mirror(txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,6+512*cely+(secnd_shade?SHADE_STEPS*512:0),last_scale,y,(clipr<<16)+clipl); + else enemy_draw(txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,6+512*cely+(secnd_shade?SHADE_STEPS*512:0),last_scale,y,(clipr<<16)+clipl); + } + +/*void draw_placed_texture(short *txtr,int celx,int cely,int posx,int posy,int posz,char turn) + { + int x,y,xsr,ysr; + long zoomtab_x[640]; + short zoomtab_y[360]; + int xs,ys,xofs,xmax; + + map_pos(celx,cely,posx,posy,posz,&x,&y); + if (y>460-SCREEN_OFFLINE) return; + xs=txtr[0]; + xsr=xs*last_scale/320; + ys=txtr[1]; + ysr=ys*last_scale/320; + if (turn) x=VIEW_SIZE_X-x; + x-=xsr/2; + y+=ysr/2; + if (-x>=xsr || x>VIEW_SIZE_X) return; + if (x<0) + { + xofs=-x*xs/xsr; + xmax=xsr+x; + x=0; + } + else if (x+xsr>VIEW_SIZE_X) + { + xofs=0; + xmax=VIEW_SIZE_X-x; + } + else + { + xofs=0; + xmax=xsr; + } + calc_x_buffer((long *)&zoomtab_x,320,last_scale,640,last_scale); + calc_y_buffer((short *)&zoomtab_y,320,last_scale,360); + if (y-ysr<0) ysr=y; + if (ysr<=0) return; + if (turn) zoom.startptr=GetBuffer2nd()+y*640+(VIEW_SIZE_X-x)+SCREEN_OFFSET; + else zoom.startptr=GetBuffer2nd()+y*640+x+SCREEN_OFFSET; + zoom.texture=(short *)((char *)(&txtr[3+SHADE_PAL])+xofs); + zoom.texture_line=xs; + zoom.xtable=(long *)&zoomtab_x; + zoom.ytable=(short *)&zoomtab_y; + zoom.palette=(word *)&txtr[3+cely*256+(secnd_shade?SHADE_STEPS*256:0)]; + zoom.ycount=ysr; + zoom.xmax=xmax; + zoom.line_len=1280; + if (turn) sikma_zprava();else sikma_zleva(); + + } + */ + +void set_lclip_rclip(int celx,int cely,int lc,int rc) + { + int x,xs; + lclip=0; + rclip=640; + if (celx>=0) + { + if (rc) + { + x=points[celx][0][cely].x+MIDDLE_X; + xs=points[celx][0][cely].x-points[celx][0][cely+1].x; + rclip=x-rc*xs/TXT_SIZE_X_3D; + if (rclip>640) rclip=640; + } + if (celx>0 && lc) + { + lclip=points[celx-1][0][cely].x+MIDDLE_X; + if (lclip>rclip) lclip=rclip; + } + + } + if (celx<=0) + { + if (lc) + { + int cc=-celx; + x=-points[cc][0][cely].x+MIDDLE_X; + xs=points[cc][0][cely].x-points[cc][0][cely+1].x; + lclip=x+lc*xs/TXT_SIZE_X_3D; + if (lclip<0) lclip=0; + } + if (celx<0 && rc) + { + rclip=-points[(-celx)-1][0][cely].x+MIDDLE_X; + if (rclipstoned) + { + unsigned short *p=(unsigned short *)alloca(SHADE_PAL); + int i; + for (i=0;ipalette[0][i]; + int bw=(GET_R_COLOR(col)+GET_G_COLOR(col)+GET_B_COLOR(col))/3; + if (bw>255) bw=255; + p[i]=RGB(bw,bw,bw); + } + drw->palette=(palette_t *)p; + } + + posx=drw->posx; + posy=drw->posy; + cely=drw->cely; + if (drw->txtr==NULL) return; + posx+=64; + if (!(drw->shiftup & 0x8)) posy+=32; + if (drw->shiftup & 0x1) posy+=128; + if (posy<0 || posy>127) return; + map_pos(drw->celx,drw->cely,posx,posy,0,&x,&y); + xs=(short *)drw->txtr; + xss=*xs*last_scale/320; + if (xss>640) return; + ys=(short *)drw->txtr+1; + yss=*ys*last_scale/320; + lx=x; + grcel=cely; + if (posy>64) grcel++; + if (grcel) grcel--; + if (cely) cely-=1; + x-=(drw->adjust*last_scale)/320; + if (x0) + if (drw->mirror)enemy_draw_mirror_transp(drw->txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,drw->palette+grcel+(secnd_shade?SHADE_STEPS:0),last_scale,y+1,(clipr<<16)+clipl); +else enemy_draw_transp(drw->txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,drw->palette+grcel+(secnd_shade?SHADE_STEPS:0),last_scale,y+1,(clipr<<16)+clipl); + if (show_lives) + { + char s[25]; + + RedirectScreenBufferSecond(); + sprintf(s,"%d",drw->num); + sd=text_width(s)/2; + if (lx-sd>0 && lx+sd<639) + { + int ly=y+SCREEN_OFFLINE-last_scale*5/6; + trans_bar(lx-sd-5,ly-10,sd*2+10,10,0); + set_aligned_position(lx,ly,1,2,s);outtext(s); + } + RestoreScreen(); + } + } + +void draw_player(short *txtr,int celx,int cely,int posx,int posy,int adjust,char *name) + { + int x,y,yc,lx,sd; + int clipl,clipr; + + RedirectScreenBufferSecond(); + map_pos(celx,cely,posx+64,posy+64,0,&x,&y); + lx=x; + x-=(adjust*last_scale)/320; + yc=(20*last_scale)/320+y; + if (x<0) + { + clipl=-x; + x=0; + } + else clipl=0; + clipr=640-x; + if (clipr>0) + enemy_draw(txtr,GetBuffer2nd()+x+(yc+SCREEN_OFFLINE)*scr_linelen2,6+512*cely+(secnd_shade?SHADE_STEPS*512:0),last_scale,y,(clipr<<16)+clipl); + if (show_names && name!=NULL) + { + sd=text_width(name)/2; + if (lx-sd>0 && lx+sd<639) + { + int ly=y+SCREEN_OFFLINE-last_scale*5/6; + trans_bar(lx-sd-5,ly-10,sd*2+10,10,0); + set_aligned_position(lx,ly,1,2,name);outtext(name); + } + } + RestoreScreen(); + } + + +void draw_spectxtr(short *txtr,int celx,int cely,int xpos) + { + int x,y,lx,clipl,clipr; + map_pos(celx,cely,64,64,0,&x,&y); + lx=x; + x-=(((*txtr>>1)+xpos)*last_scale*2)/320; + if (x<0) + { + clipl=-x; + x=0; + } + else clipl=0; + clipr=640-x; + if (clipr>0) + enemy_draw_transp(txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,(char *)txtr+6+512*cely+(secnd_shade?SHADE_STEPS*512:0),last_scale*2,y,(clipr<<16)+clipl); + } + + +void draw_item2(int celx,int cely,int xpos,int ypos,void *txtr,int index) + { + int x,y,xs,ys,ysc,abc,asc,clipl,clipr; + static int indextab[][2]={{0,0},{0,1},{1,0},{-1,0},{1,2},{-1,1},{-2,1},{2,1}}; + + celx--; + asc=(celx<0); + abc=abs(celx);if (asc) abc--; + x=points[abc][0][cely+1].x; + y=points[abc][0][cely+1].y; + xs=showtabs.x_table[0][cely].max_x; + ys=showtabs.y_table[cely+1].vert_size; + ysc=showtabs.y_table[cely].vert_size; + xpos+=indextab[7-index][0]; + ypos+=indextab[7-index][1]; + xpos-=*(word *)txtr/2; + xpos=xs*xpos/500; + ypos=ys*ypos/320; + if (asc) x=-x; + x+=MIDDLE_X; + y+=MIDDLE_Y; + x+=xpos; + y-=ypos; + if (x<0) + { + clipl=-x; + x=0; + } + else clipl=0; + clipr=640-x; + if (clipr>0) + enemy_draw(txtr,GetBuffer2nd()+x+(y+SCREEN_OFFLINE)*scr_linelen2,6+512*cely+(secnd_shade?SHADE_STEPS*512:0),ys,y,(clipr<<16)+clipl); + } + +/* +void main() + { + printf("%d\n",sizeof(showtabs)); + p=load_file("konvert\\bredy.hi"); + calc_points(); + create_tables(); + create_zooming(); + ask_video(); + put_picture(0,100,p);showview(0,0,0,0);free(p); + p2=load_file("konvert\\stena2.hi"); + p=load_file("konvert\\stena2bl.hi"); + strop=load_file("konvert\\strop1.hi"); + podlaha=load_file("konvert\\podlaha1.hi"); + sit=load_file("konvert\\sit.hi"); + build_map(); + render_scene(22,0);showview(0,0,0,0); + chozeni(); + closemode(); + } +*/ + + +int zoom_speed(int zoomspeed) + { + switch (zoomspeed) + { + case 0:zooming_step=0;break; + case 1:zooming_step=2;break; + case 2:zooming_step=1;break; + case -1: switch (zooming_step) + { + case 0:return 0; + case 1:return 2; + case 2:return 1; + } + } + return zoomspeed; + } + + +int turn_speed(int turnspeed) + { + switch (turnspeed) + { + case 0:rot_phases=0;break; + case 1:rot_phases=1;break; + case 2:rot_phases=2;break; + case -1: return rot_phases; + } + return rot_phases; + } + +void set_backgrnd_mode(int mode) + { + backgrnd_mode=mode; + } + +int get_item_top(int celx,int cely,int posx,int posy,word *txtr,int index) + { + int x,y; + int randx,randy; + + randx=items_indextab[7-(index & 0x7)][0]; + randy=items_indextab[7-(index & 0x7)][1]; + map_pos(celx,cely,42*posx+42+randx,72*posy+randy,0,&x,&y); + if (txtr!=NULL) return y-(txtr[1]*last_scale)/320+SCREEN_OFFLINE; + else return y+SCREEN_OFFLINE; + } diff --git a/GAME/ENGINE1.H b/GAME/ENGINE1.H new file mode 100644 index 0000000..be1dac0 --- /dev/null +++ b/GAME/ENGINE1.H @@ -0,0 +1,162 @@ +#ifndef __ENGINE1_H +#define __ENGINE1_H +#define VIEW_SIZE_X 640 +#define VIEW_SIZE_Y 360 +#define TAB_SIZE_X 640 +#define TAB_SIZE_Y 600 +#define MIDDLE_X 320 +#define MIDDLE_Y 112 +#define TXT_SIZE_Y 320 +#define TXT_SIZE_X_3D 74 +#define TXT_SIZE_X 500 +#define VIEW3D_X 4 +#define VIEW3D_Z 5 +#define START_X1 357 +#define START_Y1 305 +#define START_X2 357 +#define START_Y2 -150 +#define FACTOR_3D 3.33 +#define ZOOM_PHASES 9 +#define SCREEN_OFFLINE (17) +#define SCREEN_OFFSET (scr_linelen2*SCREEN_OFFLINE) +#define C_YMAP_SIZE 90 +#define F_YMAP_SIZE 199 +#define CF_XMAP_SIZE 7 + +#define SHADE_STEPS 5 +#define SHADE_PAL (SHADE_STEPS*512*2) + + +void general_engine_init(void); +void draw_floor_ceil(int celx,int cely,char f_c,void *txtr); +void show_cel2(int celx,int cely,void *stena,int xofs,int yofs,char rev); + //zobrazi primou stenu ktera lezi pred nebo napravo od pozorovatele +void show_cel(int celx,int cely,void *stena,int xofs,int yofs,char rev); + void turn_left(); +void turn_right(); +void zooming_backward(word *background); +void zooming_forward(word *background); +void OutBuffer2nd(void); +void CopyBuffer2nd(void); +void report_mode(int); +void draw_item(int celx,int cely,int posx,int posy,short *pic,int index); +void draw_item2(int celx,int cely,int xpos,int ypos,void *texture,int index); +//void textmode_effekt(); +//#pragma aux textmode_effekt modify[eax ebx ecx edx edi]; + + +void clear_buff(word *background,word backcolor,int lines); + +typedef struct zoominfo + { + void *startptr, *texture; + long texture_line,line_len; + long *xtable; + short *ytable; + word *palette; + word ycount; + word xmax; + }ZOOMINFO; + + +typedef struct t_info_y + { + long drawline; //ukazatel na radku na ktere bude stena zacinat + word vert_size; //konecna velikost steny, pokud ma pocatecni velikost TXT_SIZE_Y + word vert_total; //maximalni velikost textury aby jeste nepresahla obrazovku + short zoom_table[TAB_SIZE_Y]; //tabulka pro zoomovaci rutiny + }T_INFO_Y; + +typedef struct t_info_x_3d + { + char used; // 1 pokud je tato strana videt + integer xpos; //bod od leveho okraje + word txtoffset; //posunuti x vuci texture + word point_total; //rozdil mezi levym prednim a levym zadnim okrajem postranni steny (v adresach) + long zoom_table[VIEW_SIZE_X]; //zoomovaci tabulka pro osu x pro postranni steny + }T_INFO_X_3D; + +typedef struct t_info_x + { + char used; // 1 pokud je tato strana videt + integer xpos; //bod od leveho okraje + integer xpos2; //totez ale pro pravou stranu + word txtoffset; //posunuti x vuci texture + word max_x; //pocet viditelnych bodu z textury + word point_total; //celkovy pocet adres mezi levym a pravym okrajem + long zoom_table[VIEW_SIZE_X]; //zoomovaci tabulka pro osu x pro kolme steny + }T_INFO_X; + +typedef struct t_floor_map + { + long lineofs,linesize,counter,txtrofs; + }T_FLOOR_MAP; + +typedef struct all_view + { + T_INFO_Y y_table[VIEW3D_Z+1]; + T_INFO_X_3D z_table[VIEW3D_X][VIEW3D_Z]; + T_INFO_X x_table[VIEW3D_X][VIEW3D_Z+1]; + T_FLOOR_MAP f_table[CF_XMAP_SIZE][F_YMAP_SIZE]; + T_FLOOR_MAP c_table[CF_XMAP_SIZE][C_YMAP_SIZE]; + + }ALL_VIEW; + +typedef struct t_point + { + int x,y; + }T_POINT; + +typedef T_POINT t_points[VIEW3D_X+1][2][VIEW3D_Z+1]; +extern word *background; +extern t_points points; +extern int zooming_step; +extern int rot_phases; +extern int rot_step; +extern word *buffer_2nd; +extern char show_names; +extern char show_lives; +extern char secnd_shade; + +typedef short palette_t[256]; + +typedef struct drw_enemy_struct + { + void *txtr; + int celx,cely,posx,posy,adjust,shiftup,num; + char mirror; + char stoned; + palette_t *palette; + }DRW_ENEMY; + + + + +void enemy_draw(void *src,void *trg,int shade,int scale,int maxspace,int clip); +//#pragma aux enemy_draw parm[ESI][EDI][EBX][EDX][EAX][ECX] +void enemy_draw_transp(void *src,void *trg,void *shade,int scale,int maxspace,int clip); +//#pragma aux enemy_draw_transp parm[ESI][EDI][EBX][EDX][EAX][ECX] +void enemy_draw_mirror_transp(void *src,void *trg,void *shade,int scale,int maxspace,int clip); +//#pragma aux enemy_draw_mirror_transp parm[ESI][EDI][EBX][EDX][EAX][ECX] +void enemy_draw_mirror(void *src,void *trg,int shade,int scale,int maxspace,int clip); +//#pragma aux enemy_draw_mirror parm[ESI][EDI][EBX][EDX][EAX][ECX] +//clip je v poradi vpravo - vlevo (HiLo) + +void draw_enemy(DRW_ENEMY *drw); +void draw_player(short *txtr,int celx,int cely,int posx,int posy,int adjust,char *name); + +void set_lclip_rclip(int celx,int cely,int lc,int rc); +void draw_spectxtr(short *txtr,int celx,int cely,int xpos); + +int turn_speed(int turnspeed); //oba je nutne volat na zacatku +int zoom_speed(int zoomspeed); + +void scroll_and_copy(void *pic,void *slide, void *scr, int size,int shift, void *lineinfo); +//#pragma aux scroll_and_copy parm[esi][ebx][edi][ecx][edx][eax] + +void set_backgrnd_mode(int mode); + +int get_item_top(int celx,int cely,int posx,int posy,word *txtr,int index); + //vraci nejnizsi souradnici y predmetu leziciho na zemi v celx, cely na pozici posx,posy; + +#endif diff --git a/GAME/ENGINE2.ASM b/GAME/ENGINE2.ASM new file mode 100644 index 0000000..bea9b89 --- /dev/null +++ b/GAME/ENGINE2.ASM @@ -0,0 +1,2188 @@ +.model small +.386 + +DGROUP group _DATA + +tzoom struc + startptr DD ? ;0 + texture DD ? ;4 + textline DD ? ;8 + linelen DD ? ;12 + xtable DD ? ;16 + ytable DD ? ;20 + palette DD ? ;24 + ycount DW ? ;28 + xmax DW ? +tzoom ends + +extrn _zoom:dword [8] +extrn _lbuffer:dword +extrn _screen:dword +extrn _gran_mask:dword +extrn _lastbank:dword + +_TEXT segment byte public 'CODE' use32 + assume CS:_TEXT + assume DS:DGROUP + +extrn mapvesaadr_:proc +extrn switchmap_:proc +extrn switchvesabank_:proc + + public sikma_zleva_ +sikma_zleva_: + mov edi,_zoom ;nacti ukazatel do obrazovky + mov ebx,_zoom[offset tzoom.palette] ;ukazatel na paletu + mov cx,word ptr _zoom[offset tzoom.ycount] ;velikost textury na y + shl ecx,16 ;vloz do horni pulky ecx + mov esi,_zoom[offset tzoom.texture] ;nacti ukazatel na texturu +skzl3: mov edx,_zoom[offset tzoom.xtable] ;nacti ukazetel na zvetsovaci tabulku x + push esi ;uchovej esi + push edi ;uchovej edi + mov cx,_zoom[offset tzoom.xmax] +skzl1: xor eax,eax ;vynuluj eax pro spravny vypocet + lodsb ;nacti bod + add esi,[edx] ;posun se od nekolik pozic v texture podle hodnoty v tabulce x + add edx,4 ;posun se v tabulce x o dalsi polozku + or al,al ;test bodu na nulu + jz skz1 ;preskoc transparetni barvu + cmp al,1 ;test bodu na jedna + jz skz2 ;ukonci kresleni linky pokud narazi na 1 + mov ax,[eax*2+ebx] ;konverze barvy podle palety + mov [edi],ax ;nakresli bod na obrazovce +skz1: add edi,2 ;dalsi pozice + dec cx + jnz skzl1 ;opakuj dokola +skz2: pop edi ;obnov edi + pop esi ;obnov esi + mov edx,_zoom[offset tzoom.ytable] ;vyzvedni ukazatel na ytable + mov cx,[edx] ;cx - o kolik pozic se mam v texture posunout dolu + or cx,cx + jz skzskp +skzl2: add esi,_zoom[offset tzoom.textline] ;posun o jednu pozici + dec cx ;sniz citac + jnz skzl2 ;dokud neni nula +skzskp:add edx,2 ;dalsi hodnota v tabulce + mov _zoom[offset tzoom.ytable],edx ;uloaz na puvodni misto + sub edi,_zoom[offset tzoom.linelen] ;odecti tolik, kolik odpovida lince na obrazovce + sub ecx,10000h ;sniz horni pulku ecx o jedna + jnz skzl3 ;opakuj dokud neni nula + ret + + public sikma_zprava_ +sikma_zprava_: + mov edi,_zoom ;nacti ukazatel do obrazovky + mov ebx,_zoom[offset tzoom.palette] ;ukazatel na paletu + mov cx,word ptr _zoom[offset tzoom.ycount] ;velikost textury na y + shl ecx,16 ;vloz do horni pulky ecx + mov esi,_zoom[offset tzoom.texture] ;nacti ukazatel na texturu +skzp3: mov edx,_zoom[offset tzoom.xtable] ;nacti ukazetel na zvetsovaci tabulku x + push esi ;uchovej esi + push edi ;uchovej edi + mov cx,_zoom[offset tzoom.xmax] +skzp1: xor eax,eax ;vynuluj eax pro spravny vypocet + lodsb ;nacti bod + add esi,[edx] ;posun se od nekolik pozic v texture podle hodnoty v tabulce x + add edx,4 ;posun se v tabulce x o dalsi polozku + or al,al ;test bodu na nulu + jz skz3 ;preskoc transparetni barvu + cmp al,1 ;test bodu na jedna + jz skz4 ;ukonci kresleni linky pokud narazi na 1 + mov ax,[eax*2+ebx] ;konverze barvy podle palety + mov [edi],ax ;nakresli bod na obrazovce +skz3: sub edi,2 ;dalsi pozice + dec cx + jnz skzp1 ;opakuj dokola +skz4: pop edi ;obnov edi + pop esi ;obnov esi + mov edx,_zoom[offset tzoom.ytable] ;vyzvedni ukazatel na ytable + mov cx,[edx] ;cx - o kolik pozic se mam v texture posunout dolu + or cx,cx + jz skpskp +skzp2: add esi,_zoom[offset tzoom.textline] ;posun o jednu pozici + dec cx ;sniz citac + jnz skzp2 ;dokud neni nula +skpskp: add edx,2 ;dalsi hodnota v tabulce + mov _zoom[offset tzoom.ytable],edx ;uloaz na puvodni misto + sub edi,_zoom[offset tzoom.linelen] ;odecti tolik, kolik odpovida lince na obrazovce + sub ecx,10000h ;sniz horni pulku ecx o jedna + jnz skzp3 ;opakuj dokud neni nula + ret + + + public zooming32_ +zooming32_: + ;esi - zdrojovy blok + ;edi - cil + ;eax - pozadi + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + push ebp + mov ebp,eax + mov ebx,_zoom[offset tzoom.ytable] +z32d: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi +z32c: mov al,[edx] + inc edx + or al,al + jz z32a + lodsw + test ax,8000h + jnz z32e + stosw + stosw + jmp z32b +z32f: test eax,8000h + jz z32g + test eax,80000000h + jz z32h +z32e: mov eax,[ds:ebp] + stosd + jmp z32b +z32g: rol eax,16 + mov ax,[ds:ebp+2] + rol eax,16 + stosd + jmp z32b +z32h: mov ax,[ds:ebp] + stosd + jmp z32b +z32a: lodsd + test eax,80008000h + jnz z32f + stosd +z32b: add ebp,4 + dec cx + jnz z32c + pop esi + mov eax,[ebx] + and eax,0ffffh + add esi,eax + add ebx,2 + add edi,_zoom[offset tzoom.textline] + xor cx,cx + sub ecx,10000h + pop cx + jnz z32d + pop ebp + ret + + public zooming32b_ +zooming32b_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.ytable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;zoom.ycount - interni (ulozeni maskovane adr stranky) + ;zoom.xmax - interni (pocet dwordu do prepnuti) + ;zoom.linelen - interni (velikost stranky v dwordech) + + + call mapvesaadr_ ;mapuj spravne edi + push ebp + mov ebp,eax + mov ebx,_zoom[offset tzoom.ytable] +z32bd: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi + push edi +z32bc: mov al,[edx] + inc edx + or al,al + jz z32ba + lodsw + test ax,8000h + jnz z32be + stosw + stosw + jmp z32bb +z32bf: test eax,8000h + jz z32bg + test eax,80000000h + jz z32bh +z32be: mov eax,[ds:ebp] + stosd + jmp z32bb +z32bg: rol eax,16 + mov ax,[ds:ebp+2] + rol eax,16 + stosd + jmp z32bb +z32bh: mov ax,[ds:ebp] + stosd + jmp z32bb +z32ba: lodsd + test eax,80008000h + jnz z32bf + stosd +z32bb: add ebp,4 + movzx eax,di ;prevezmi dolni cast edi do eax + dec eax ;odecti 1 (0=0xffffffff) + cmp eax,_gran_mask ;je vetsi nez granualita? + jc z32gb ;ne, vse je ok + mov eax,_lastbank ;ano, pak vem cislo banky + inc eax ;pricti 1 + mov _lastbank,eax ;zapis jako nove cislo banky + pushad ;uchovej vse + call switchvesabank_ ;prepni banku + popad ;obnov vse + mov edi,0a0000h ;vynuluj dolni cast di +z32gb: dec cx ;tady pokracujem + jnz z32bc ;opakuj cxkrat + pop edi ;obnov edi + add di,1280 ;pricti radek + and di,word ptr _gran_mask ;maskuj granualitou + pop esi + mov eax,[ebx] + and eax,0ffffh + add esi,eax + add ebx,2 + xor cx,cx + sub ecx,10000h + pop cx + jnz z32bd + pop ebp + ret + + + + public zooming_lo_ +zooming_lo_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;ebx xlat + push ebp + mov bp,cx +zlod: mov cx,bp + mov edx,_zoom[offset tzoom.xtable] + push esi +zloc: xor eax,eax + mov al,[edx] + inc edx + or al,al + jz zloa + lodsw + mov eax,[ebx+eax*2] + stosb + jmp zlob +zloa: lodsw + mov eax,[ebx+eax*2] + stosb + add esi,2 +zlob: dec cx + jnz zloc + pop esi + mov edx,_zoom[offset tzoom.ytable] + mov eax,[edx] + shl eax,1 + and eax,0ffffh + add esi,eax + add edx,2 + mov _zoom[offset tzoom.ytable],edx + add edi,_zoom[offset tzoom.textline] + xor cx,cx + sub ecx,20000h + jnz zlod + pop ebp + ret + + public zooming256_ +zooming256_: + ;esi - zdrojovy blok + ;edi - cil + ;eax - pozadi + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;ebx xlat + push ebp + mov ebp,eax +z256d: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi +z256c: xor eax,eax + mov al,[edx] + inc edx + or al,al + jz z256a + lodsw + test eax,8000h + jnz z256e + mov al,[ebx+eax*2] + mov ah,al + stosw + jmp z256b +z256e: mov ax,[ds:ebp] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + mov ax,[ds:ebp+2] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256b +z256g: mov ax,[ds:ebp] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256h +z256i: mov ax,[ds:ebp+2] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256b +z256a: lodsw + test eax,8000h + jnz z256g + mov al,[ebx+eax*2] + stosb +z256h: lodsw + test eax,8000h + jnz z256i + mov al,[ebx+eax*2] + stosb +z256b: add ebp,4 + xor ebx,1 + dec cx + jnz z256c + xor ebx,1 + pop esi + mov edx,_zoom[offset tzoom.ytable] + mov eax,[edx] + and eax,0ffffh + add esi,eax + add edx,2 + mov _zoom[offset tzoom.ytable],edx + add edi,_zoom[offset tzoom.textline] + xor cx,cx + sub ecx,10000h + pop cx + jnz z256d + pop ebp + ret + +swap_at_end macro reg16,reg32 + local sw1,sw2 + +sw2: movzx eax,reg16 ;nacti 16 bitovou cast registru + dec eax ;sniz ke kontrole o 1 + cmp eax,_gran_mask ;kontrola zda je vetsi nebo rovny masce + jc sw1 ;kdyz ne tak preskoc na sw1 + mov eax,_lastbank ;vem cislo banky + inc eax ;pricti jednicku + mov _lastbank,eax ;vloz zpatky do banky + pushad + call switchvesabank_ ;prepni banku + popad + sub reg32,_gran_mask ;odecti delku stranky od cele adresy + dec reg32 +sw1: +endm + + + public zooming256b_ +zooming256b_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;ebx xlat + push ebp + mov ebp,eax +z256bd: push cx + mov edx,_zoom[offset tzoom.xtable] + push edi + call mapvesaadr_ + push esi +z256bc: xor eax,eax + mov al,[edx] + inc edx + or al,al + jz z256ba + lodsw + test eax,8000h + jnz z256be + mov al,[ebx+eax*2] + mov ah,al + stosw + jmp z256bb +z256be: mov ax,[ds:ebp] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + mov ax,[ds:ebp+2] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256bb +z256bg: mov ax,[ds:ebp] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256bh +z256bi: mov ax,[ds:ebp+2] + and eax,7fffh + mov al,[ebx+eax*2] + stosb + jmp z256bb +z256ba: lodsw + test eax,8000h + jnz z256bg + mov al,[ebx+eax*2] + stosb +z256bh: lodsw + test eax,8000h + jnz z256bi + mov al,[ebx+eax*2] + stosb +z256bb: add ebp,4 + swap_at_end di,edi + xor ebx,1 + dec cx + jnz z256bc + xor ebx,1 + pop esi + pop edi + add edi,640 + mov edx,_zoom[offset tzoom.ytable] + mov eax,[edx] + and eax,0ffffh + add esi,eax + add edx,2 + mov _zoom[offset tzoom.ytable],edx + add edi,_zoom[offset tzoom.textline] + xor cx,cx + sub ecx,10000h + pop cx + jnz z256bd + pop ebp + ret + +; public scroll_left_ +;scroll_left_: ;edi - kam +; ;lbuffer - obrazovka +; ;zoom.startptr - novy obsah obrazovky +; ;ebx - xlat +; ;eax - o_kolik +; mov bx,ax ;horni pulka ebx vi o kolik se posunuje vlevo +; rol ebx,16 +; mov edx,640 ;dolni pulka ebx vi, jak velky blok je presouvan +; sub edx,eax +; sub edx,2 + ; mov bx,dx + ; mov esi,edi ;vypocet esi + ; shl eax,1 ;esi = edi + 2 * o_kolik; + ; add esi,eax + ; mov edx,360 ;napln citac edx cislem udavajici pocet radku + ; add edi,_lbuffer ;k edi na zacatku pricti hodnotu _lbuffer + ; mov eax,esi ;uchovej esi v eax, behem prenosu bude modifikovan +;scrl1: add esi,_lbuffer ;pricti k esi zacatek obrazovky +; xor ecx,ecx ;vynuluj ecx +; mov cx,bx ;do ecx naladuj delku bloku +; shr ecx,1 ;presun 32-bit +; rep movsd +; adc ecx,1 +;; rep movsw +; mov esi,_zoom ;vem ukazatel na novy obsah +; mov ecx,ebx ;vezmi horni pulku EBx +; shr ecx,16 ;to je hodnota, kolik se ma v prava doplnit +; shr ecx,1 ;presun 32-bit +; rep movsd + ; adc ecx,1 + ; rep movsw + ; add _zoom,640*2 ;dalsi radka + ;; add eax,640*2 ;dalsi radka +; mov esi,eax +; dec edx ;dokud neni konec + ; jnz scrl1 + ; ret + ; + +public scroll_support_32_ +scroll_support_32_: + ;edi - lbuffer + pozice na obrazovce + ;esi - oldbuffer + ;edx - newbuffer + ;ebx - xlat + ;ecx - size; + push ebp ;uchovej ebp + mov ebp,360 ;ebp pro tuto chvili predstavuje citac + mov eax,ecx ;uchovej ecx jeste v eac - zachova citac sloupcu +scrl1: push esi ;uchovej esi + shr ecx,1 ;presun ecx bloku + rep movsd + rcl ecx,1 + rep movsw + mov ecx,640 ;dopocitej ecx do 640 + sub ecx,eax + pop esi ;obnov esi + xchg esi,edx ;esi je nyni novy blok + push esi ;uchovek esi + shr ecx,1 ;presun + rep movsd + rcl ecx,1 + rep movsw + pop esi ;obnov esi + xchg esi,edx ;vrat edx a esi do puvodniho stavu + mov ecx,eax ;obnov zase ecx z eax + add esi,1280 ;dalsi radek + add edx,1280 + dec ebp ; dokud nejsme na konci + jnz scrl1 ;opakuj + pop ebp + ret + +movsdx macro ;presun do videopameti s kontrolou na banky + local sw1,konec + push eax + movzx eax,di + add eax,ecx + cmp eax,_gran_mask + ja sw1 + shr ecx,2 + rep movsd + jmp konec +sw1: mov eax,_gran_mask + sub ax,di + inc eax + sub ecx,eax + xchg eax,ecx + shr ecx,2 + rep movsd + xchg eax,ecx + mov eax,_lastbank + inc eax + mov _lastbank,eax + pushad + call switchvesabank_ + popad + mov edi,0a0000h + shr ecx,2 + rep movsd +konec: pop eax +endm +public scroll_support_32b_ +scroll_support_32b_: + ;edi - lbuffer + pozice na obrazovce /pokud mozno del 4 + ;esi - oldbuffer + ;edx - newbuffer + ;ebx - xlat + ;ecx - size pokud mozno / 4; + call mapvesaadr_ ;mapuj spravne edi + push ebp ;uchovej ebp + mov ebp,360 ;ebp pro tuto chvili predstavuje citac + and ecx,not 1 + shl ecx,1 ;korekce ecx na delitele 4x + mov eax,ecx ;uchovej ecx jeste v eax - zachova citac sloupcu +scrl1b: push esi ;uchovej esi + movsdx ;presun ecx bajtu (jen ctverice) + mov ecx,1280 ;dopocitej ecx do 640 + sub ecx,eax + pop esi ;obnov esi + xchg esi,edx ;esi je nyni novy blok + push esi ;uchovek esi + movsdx + pop esi ;obnov esi + xchg esi,edx ;vrat edx a esi do puvodniho stavu + mov ecx,eax ;obnov zase ecx z eax + add esi,1280 ;dalsi radek + add edx,1280 + dec ebp ; dokud nejsme na konci + jnz scrl1b ;opakuj + pop ebp + ret + + +public scroll_support_256_ +scroll_support_256_: + ;edi - lbuffer + pozice na obrazovce + ;esi - oldbuffer + ;edx - newbuffer + ;ebx - xlat + ;ecx - size; + push ebp ;uchovej ebp + mov ebp,360 ;ebp pro tuto chvili predstavuje citac +scrl1a: push ecx ;uchovej ecx jeste v eac - zachova citac sloupcu + push esi ;uchovej esi +scrl2a: lodsw + and eax,7fffh + mov al,[ebx+2*eax] + xor ebx,1 + stosb + dec ecx + jnz scrl2a + pop esi + xchg esi,edx ;esi je nyni novy blok + pop eax + mov ecx,640 ;dopocitej ecx do 640 + sub ecx,eax + push eax + push esi ;uchovek esi +scrl3a: lodsw + and eax,7fffh + mov al,[ebx+2*eax] + xor ebx,1 + stosb + dec ecx + jnz scrl3a + pop esi ;obnov esi + xchg esi,edx ;vrat edx a esi do puvodniho stavu + pop ecx ;obnov zase ecx z eax + add esi,1280 ;dalsi radek + add edx,1280 + xor ebx,1 + dec ebp ; dokud nejsme na konci + jnz scrl1a ;opakuj + pop ebp + ret + +public scroll_support_256b_ +scroll_support_256b_: + ;edi - lbuffer + pozice na obrazovce + ;esi - oldbuffer + ;edx - newbuffer + ;ebx - xlat + ;ecx - size; + call mapvesaadr_ + push ebp ;uchovej ebp + mov eax,360 ;eax pro tuto chvili predstavuje citac + mov ebp,edx +scrl1ba:push eax + push ecx ;uchovej ecx jeste v eac - zachova citac sloupcu + push esi ;uchovej esi + xor eax,eax + shr ecx,1 +scrl2ba:lodsw + and eax,7fffh + mov dl,[ebx+2*eax] + xor ebx,1 + lodsw + and eax,7fffh + mov dh,[ebx+2*eax] + xor ebx,1 + mov [edi],dx + add edi,2 + swap_at_end di,edi + dec ecx + jnz scrl2ba + pop esi + xchg esi,ebp ;esi je nyni novy blok + pop eax + mov ecx,640 ;dopocitej ecx do 640 + sub ecx,eax + push eax + push esi ;uchovek esi + xor eax,eax + shr ecx,1 +scrl3ba:lodsw + and eax,7fffh + mov dl,[ebx+2*eax] + xor ebx,1 + lodsw + and eax,7fffh + mov dh,[ebx+2*eax] + xor ebx,1 + mov [edi],dx + add edi,2 + swap_at_end di,edi + dec ecx + jnz scrl3ba + pop esi ;obnov esi + xchg esi,ebp ;vrat ebp a esi do puvodniho stavu + pop ecx ;obnov zase ecx z eax + pop eax + add esi,1280 ;dalsi radek + add ebp,1280 + xor ebx,1 + dec eax ; dokud nejsme na konci + jnz scrl1ba ;opakuj + pop ebp + ret + + + +public fcdraw_ ;Kresli strop nebo podlahu podle draw_table + ;EDX - sourceTxt + ;EBX - TargerTxt - LineOfset + ; (Lineofs je pocet bajtu odpovidajici + ; souradnicim [0,184] pro podlahu nebo [0,0] + ; pro strop) + ;EAX - draw_table +fcdraw_:mov esi,[eax] + mov edi,esi + add edi,ebx + add esi,edx + mov ecx,[eax+4] + shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,[eax+8] + add eax,12 + or ecx,ecx + jnz fcdraw_ + ret + +public put_image_ ;vlozi obrazek v hicolor +put_image_: ;ESI - obrazek + ;EDI - obrazovka + ;EAX - startline + ;EBX - velikostx + ;EDX - velikosty + shl eax,1 + xor ecx,ecx + mov cx,[esi] + imul eax,ecx + add esi,eax + add esi,6 + mov eax,ecx +puti_lp:mov ecx,ebx + shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,eax + sub ecx,ebx + add esi,ecx + sub edi,ebx + sub edi,ebx + add edi,1280 + dec edx + jnz puti_lp + ret + +public put_8bit_clipped_ ;vlozi 8bit obrazek omezen velikosti +put_8bit_clipped_: ;ESI - obrazek + ;EDI - obrazovka + ;EAX - startline + ;EBX - velikostx + ;EDX - velikosty + + push ebp + mov ebp,ebx + xor ecx,ecx + mov cx,[esi] + imul eax,ecx + lea ebx,[esi+6]; + add esi,6+512 + add esi,eax + mov eax,ecx +put8_lp:mov ecx,ebp + push eax +put8lp2:xor eax,eax + lodsb + or eax,eax + jz put8_trns + mov eax,[ebx+eax*2] + stosw +put8nxt:dec ecx + jnz put8lp2 + pop eax + mov ecx,eax + sub ecx,ebp + add esi,ecx + sub edi,ebp + sub edi,ebp + add edi,1280 + dec edx + jnz put8_lp + pop ebp + ret +put8_trns: + add edi,2 + jmp put8nxt + +public textmode_effekt_ + +textmode_effekt_: ;genetuje effekt v textovem rezimu + mov edx,3c4h + mov eax,0402h + out dx,ax + mov eax,0704h + out dx,ax + Mov edx,3ceh + mov eax,0204h + out dx,ax + mov eax,0005h + out dx,ax + mov eax,0406h + out dx,ax + mov bl,8 + xor bh,bh +tde2: mov edi,0xA0000h + mov ecx,32*256 +tde1: not bh + or bh,bh + jz tde3 + shr byte ptr [edi],1 + jmp tde4 +tde3: shl byte ptr [edi],1 +tde4: inc edi + dec ecx + jnz tde1 + mov edx,0x3da + mov bh,3 +tdew2: in al,dx + and al,8 + jz tdew2 +tdew1: in al,dx + and al,8 + jnz tdew1 + dec bh + jnz tdew2 + dec bl + jnz tde2 + mov edx,3c4h + mov eax,0302h + out dx,ax + mov eax,0304h + out dx,ax + Mov edx,3ceh + mov eax,0004h + out dx,ax + mov eax,1005h + out dx,ax + mov eax,0E06h + out dx,ax + ret + +public put_textured_bar__ + ;zobrazi texturovany obdelnik tvoreny cyklickou texturou + ;vstup + ; EDI - pozice na obrazovce + ; EBX - textura + ; ECX - velikosty + ; EDX - velikostx + ; EAX - yofs + ; ESI - xofs + +put_textured_bar__: + push ebp ;uchovej EBP - bude pouzit jako univerzalni registr + mov ebp,eax ;zacneme o EAX radku v texture niz + shl edx,16 ;nachvili uchovej dx v horni pulce + mul word ptr [ebx] ;zjisti pocatecni adresu v texture + shl eax,16 + shrd eax,edx,16 ;EAX=AX*word ptr[ebx] + shr edx,16 + xchg esi,eax ;napln esi pocatkem + lea esi,[esi+512] ;vypocti zacatek v texture+xlat + lea ebx,[ebx+6] ;postav ebx na zacatek xlat + add esi,ebx ;pricti zacatek textury + add esi,eax ;pricti k ukazateli ofset v x +ptb_l2: push eax ;uchovej xofset + push edx ;uchovej velikost v x + push esi ;uchovej zacatek radky v texture + shl ebp,16 ;odsun citac offset do horni pulky ebp + add bp,ax ;pricti k bp offset v x +ptb_l1: xor eax,eax ;pred kazdym bodem vynuluj eax + lodsb ;nacti barvu + or al,al + jz ptb_s1 + mov ax,[ebx+eax*2];vyhledej barvu v palete + mov [edi],ax ;zapis hicolor barvu +ptb_s1: add edi,2 + inc bp ;zvys counter v x + cmp bp,[ebx-6] ;byl dosazen pravy roh textury? + jc ptb_skip1 ;ne pokracuj + mov ax,bp ;nacti eax counterem + sub esi,eax ;odexti to cele od esi - tj spatky doleva + xor bp,bp +ptb_skip1: + dec edx + jnz ptb_l1 + shr ebp,16 ;vrat counter pro y + pop esi ;obnov pocatek v texture + mov ax,[ebx-6] ;nalouduj do eax delku x (horni pulka je zarucene prazdna) + add esi,eax ;pricti k esi + inc ebp ;zvys y counter + cmp bp,[ebx-4] ;test zda jsme dosahli dolniho rohu textury + jc ptb_skip2 ;ne pokracuj + mov eax,ebp ;ano nalouduj eax + mul word ptr [ebx-6];vynasob ho delkou v x + shl eax,16 + shrd eax,edx,16 ;eax=ax*word ptr [ebx-4] + sub esi,eax ;jsme na zacatku + xor ebp,ebp +ptb_skip2: + pop edx ;obnov zbyvajici registry + pop eax + lea edi,[edi+1280] ;presun se na dalsi radek na obrazovky + sub edi,edx + sub edi,edx + dec ecx ;odecti 1 od globalniho citace radek + jnz ptb_l2 ;konec velke smycky + POP EBP + ret + +public trans_bar_ ;kresli transparetni pravouhelnik ucite barvy + ;EDI - X + ;ESI - Y + ;ECX - YS + ;EDX - XS bere se nejmensi sude cislo + ;EBX - BARVA +trans_bar_: + mov eax,1280 + imul eax,esi + shl edi,1 + add edi,eax + add edi,_screen + mov eax,ebx + shl eax,16 + shld ebx,eax,16 + and ebx,7bde7bdeh +trs_l2: mov esi,edi + push edx + shr edx,1 +trs_l1: lodsd + and eax,7bde7bdeh + add eax,ebx + shr eax,1 + stosd + dec edx + jnz trs_l1 + pop edx + add edi,1280 + sub edi,edx + sub edi,edx + dec ecx + jnz trs_l2 + ret + +public trans_line_x_ + ;EDI - X + ;ESI - Y + ;ECX - XS + ;EDX - COLOR +trans_line_x_: + mov eax,1280 + imul eax,esi + shl edi,1 + add edi,eax + add edi,_screen + mov esi,edi + mov eax,edx + shl eax,16 + shld edx,eax,16 + and edx,7bdf7bdfh + ror ecx,1 +trlx_l: lodsd + and eax,7bdf7bdfh + add eax,edx + shr eax,1 + stosd + dec cx + jnz trlx_l + shl ecx,1 + jnc trlx_s + lodsw + and eax,7bdf7bdfh + add eax,edx + shr eax,1 + stosw +trlx_s: ret + +public trans_line_y_ + ;EDI - X + ;ESI - Y + ;ECX - YS + ;EDX - COLOR +trans_line_y_: + mov eax,1280 + imul eax,esi + shl edi,1 + add edi,eax + add edi,_screen + mov esi,edi + and edx,7bdfh +trly_l: mov ax,[esi] + and eax,7bdfh + add eax,edx + shr eax,1 + mov [esi],ax + add esi,1280 + dec ecx + jnz trly_l + ret + + +pic_start equ 2+2+2+512*5+512*5 +ed_stack equ 640*4+480*4 +ed_stk1 equ 480*4 + +public enemy_draw_ +enemy_draw_: ;ESI - Source_picture + ;EDI - Target + ;EBX - Offset of palette + ;EDX - scale (1-320) + ;EAX - max_space (kolik ma nahore mista) + ;ECX - Hi_omezeni z prava, Lo_omezeni zleva + + cmp eax,470 + jc ed_ok1 + ret +ed_ok1: push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,word ptr[esi] ;precti xs + movzx eax,word ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +ed_lp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +ed_lp1a:cmp ebp,edx + jc ed_nxt1 ;pri ebp=velikosti obrazku tak konec + jc ed_lp2a + xor eax,eax + dec eax ;zapis -1 na konec tabulky + pop ebx ; +2 + stosd + mov eax,edi ;konecnou pozici pro tabulku x zapis do eax + pop edi ;obnov registry edi exc ebx+1 + add ebx,esi ;najdi adresu prekladove tabulky barev + add ebx,2 ;preskoc transparentni barvu + add esi,pic_start;presun se na zacatek obrazku + pop ecx ; +0 + movzx edx,cx ;vem levy okraj + lea edx,[ebp+edx*4] + lea edx,[edx+ed_stk1];edx ukazuje na sloupce + cmp eax,edx ;je-li levy okraj za platnou tabulkou tak konec + jbe ed_err + shr ecx,16 ;ecx ted obsahuje pravy okraj +ed_lp4: push esi ;uchovej esi +1 + push edi ;uchovej edi +2 + add esi,[ebp] ;spocitej spravnou hodnotu esi + push ecx ;uchovej pravy okraj +3 + push edx ;uchovej ukazatel na tabulku+4 +ed_lp3: mov eax,[edx] + cmp eax,-1 ;testuj konec tabulky + jz ed_end3 ;pri pozitivnim vysledku => konec radky + movzx eax,byte ptr[esi+eax];vem barvu + or al,al + jz ed_skp1 ;preskoc transparentni barvu + dec al + jz ed_shd ;1=shadow + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp ed_skp2 +ed_shd: movzx eax,word ptr[edi];vem barvu + and eax,7bdfh ;stmav + shr eax,1 + stosw ;zapis + jmp ed_skp2 ;skok na konec +ed_skp1:add edi,2 ;preskoc bod +ed_skp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz ed_lp3 +ed_end3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,1280 ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz ed_lp4 ;jinak pokracuj +ed_err: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + ret ;konec + +public enemy_draw_mirror_ ;kresli zrcadlove otocenou potvoru +enemy_draw_mirror_: ;ESI - Source_picture + ;EDI - Target + ;EBX - Offset of palette + ;EDX - scale (1-320) + ;EAX - max_space (kolik ma nahore mista) + ;ECX - Hi_omezeni z prava, Lo_omezeni zleva + + push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,word ptr[esi] ;precti xs + movzx eax,word ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +edmlp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +edmlp1a:cmp ebp,edx + jc edmnxt1 ;pri ebp konec radky + movzx eax,byte ptr[esi+eax];vem barvu + or al,al + jz edmskp1 ;preskoc transparentni barvu + dec al + jz edmshd ;1=shadow + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp edmskp2 +edmshd: movzx eax,word ptr[edi];vem barvu + and eax,7bdfh ;stmav + shr eax,1 + stosw ;zapis + jmp edmskp2 ;skok na konec +edmskp1:add edi,2 ;preskoc bod +edmskp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz edmlp3 +edmend3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,1280 ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz edmlp4 ;jinak pokracuj +edmerr: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + ret ;konec + + +pic_start_15 equ 2+2+2+512 + + + +public put_picture2picture_ ;vlozi obrazek do obrazku (256c->256) +put_picture2picture_: + ;ESI - obrazek 256c + ;EDI - obrazek 256 + ;EAX - Xpos + ;EDX - Ypos + movzx ecx,word ptr [edi] ;vyzvedni sirku obrazku + imul edx,ecx ;nova adresa=edi+(Xpos+sirka*Ypos) + add eax,edx + mov edx,ecx + lea edi,[edi+eax+pic_start] ;edi obsahuje novou adresu + mov ecx,[esi] ;ecx obsahuje Xsize a Ysize obrazku + sub ecx,10000h ;Ysize-1 + lea esi,[esi+pic_start] ;nastav esi na zacatek bitmapy +ppp_lp2:push ecx ;uchovej velikosti obrazku v zasobniku +ppp_lp1:lodsb ;nacti bod ze zdroje + or al,al ;zkontroluj zda to neni transparentni barva + jz ppp_trn ;pokud je tak ji prezskoc + mov [edi],al ;zapis barvu +ppp_trn:inc edi ;dalsi bod + dec cx ;odecitej x sirku + jnz ppp_lp1 ;dokud to neni vse + pop ecx ;obnov ecx + movzx eax,cx ;vem jeste jednou sirku + sub eax,edx ;spocitej kolik bajtu je nutne + sub edi,eax ;prezkocit k dosazeni dalsi radky + sub ecx,10000h ;opakuj pro y radku + jnc ppp_lp2 + ret + +public trans_bar25_ ;ztmaveni o 25% + ;EDI - X + ;ESI - Y + ;ECX - YS + ;EDX - XS bere se nejmensi sude cislo +trans_bar25_: + mov eax,1280 + imul eax,esi + shl edi,1 + add edi,eax + add edi,_screen +trs2_l2:mov esi,edi + push edx + shr edx,1 +trs2_l1:lodsd + mov ebx,eax + and ebx,739c739ch + shr ebx,2 + sub eax,ebx + stosd + dec edx + jnz trs2_l1 + pop edx + add edi,1280 + sub edi,edx + sub edi,edx + dec ecx + jnz trs2_l2 + ret + + + +;public double_xicht_ ;zobrazi zvetseny xicht +; ;ESI - source +; ;EDI - TARGET +;double_xicht_: +; push ebp +; mov ecx,[esi+2] +; lea ebx,[esi+6] +; mov edx,[ebx-6] +; movzx eax,byte ptr [esi] +; mov ebp,[eax*2+ebx] + + + + +public enemy_draw_transp_ +enemy_draw_transp_: ;ESI - Source_picture + ;EDI - Target + ;EBX - Offset of palette + ;EDX - scale (1-320) + ;EAX - max_space (kolik ma nahore mista) + ;ECX - Hi_omezeni z prava, Lo_omezeni zleva + + cmp eax,470 + jc et_ok1 + ret +et_ok1: push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,word ptr[esi] ;precti xs + movzx eax,word ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +et_lp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +et_lp1a:cmp ebp,edx + jc et_nxt1 ;pri ebp=velikosti obrazku tak konec + jc et_lp2a + xor eax,eax + dec eax ;zapis -1 na konec tabulky + pop ebx ; +2 + stosd + mov eax,edi ;konecnou pozici pro tabulku x zapis do eax + pop edi ;obnov registry edi exc ebx+1 + cmp byte ptr [esi+5],2 ;obrazek bez palety? + jz et_pl1 + add esi,pic_start;presun se na zacatek obrazku (za paletu) + jmp et_pl2 +et_pl1: add esi,6 ;(obrazek bez palety, presun se za hlavicku) +et_pl2: pop ecx ; +0 + movzx edx,cx ;vem levy okraj + lea edx,[ebp+edx*4] + lea edx,[edx+ed_stk1];edx ukazuje na sloupce + cmp eax,edx ;je-li levy okraj za platnou tabulkou tak konec + jbe et_err + shr ecx,16 ;ecx ted obsahuje pravy okraj +et_lp4: push esi ;uchovej esi +1 + push edi ;uchovej edi +2 + add esi,[ebp] ;spocitej spravnou hodnotu esi + push ecx ;uchovej pravy okraj +3 + push edx ;uchovej ukazatel na tabulku+4 +et_lp3: mov eax,[edx] + cmp eax,-1 ;testuj konec tabulky + jz et_end3 ;pri pozitivnim vysledku => konec radky + movzx eax,byte ptr[esi+eax];vem barvu + test al,80h + jnz et_shd + or al,al + jz et_skp1 ;preskoc transparentni barvu + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp et_skp2 +et_shd: and word ptr[edi],07bdfh + mov eax,[ebx+eax*2];vyzvedni hicolor + and eax,7bdfh ;stmav + add ax,word ptr[edi] + shr eax,1 + stosw ;zapis + jmp et_skp2 ;skok na konec +et_skp1:add edi,2 ;preskoc bod +et_skp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz et_lp3 +et_end3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,1280 ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz et_lp4 ;jinak pokracuj +et_err: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + ret ;konec + + +public enemy_draw_mirror_transp_ ;kresli zrcadlove otocenou potvoru pruhledne +enemy_draw_mirror_transp_: ;ESI - Source_picture + ;EDI - Target + ;EBX - Offset of palette + ;EDX - scale (1-320) + ;EAX - max_space (kolik ma nahore mista) + ;ECX - Hi_omezeni z prava, Lo_omezeni zleva + + push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,word ptr[esi] ;precti xs + movzx eax,word ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +etmlp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +etmlp1a:cmp ebp,edx + jc etmnxt1 ;pri ebp konec radky + movzx eax,byte ptr[esi+eax];vem barvu + test al,80h + jnz etmshd + or al,al + jz etmskp1 ;preskoc transparentni barvu + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp etmskp2 +etmshd: and word ptr[edi],07bdfh + mov eax,[ebx+eax*2];vyzvedni hicolor + and eax,7bdfh ;stmav + add ax,word ptr[edi] + shr eax,1 + stosw ;zapis + jmp etmskp2 ;skok na konec +etmskp1:add edi,2 ;preskoc bod +etmskp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz etmlp3 +etmend3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,1280 ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz etmlp4 ;jinak pokracuj +etmerr: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + ret ;konec + + + + +zobraz_2 macro + lodsw + movzx ebp,ah + movzx ebp,ds:[ebx+ebp*2] + shl ebp,16 + movzx eax,al + movzx eax,[ebx+eax*2] + or eax,ebp + stosd +endm + +zobraz_1 macro + lodsb + movzx eax,al + movzx eax,word ptr [eax*2+ebx] + stosw +endm + + +public show_anm_buff_ ;zobrazi frame animace (normal); + +show_anm_buff_: ;ESI - SOURCE + ;EDI - TARGER + ;EBX - PALETA + + push ebp + mov ecx,180*320 +shwab4: zobraz_2 + dec ecx + jnz shwab4 + ret + +public show_anm_delta_ ;zobrazi frame animace (normal); + + +show_anm_delta_: ;ESI - SOURCE + ;EDI - TARGER + ;EBX - PALETA + + push ebp ;uchovej EBP pro dalsi mozne pouziti + mov ch,180 ;180 radek + mov eax,[esi] ;vem offset na delta data + lea ebp,[esi+eax+4] ;ebp obsahuje tento offset + lea esi,[esi+4] ;esi obsahuje offset na delta control +shwad5: push edi ;uchovej zacatek radky + push edx ;i pro transp data +shwad3: lodsb ;vem skip hodnotu + mov ah,al ;uchovej ji ah - kvuli destruktivnimu testu + and al,not 3fh ;na posledni 2 bity + cmp al,0c0h ;C0 a vyssi znamenaji ze se preskakuje radek + jz shwad1 ;pri pozitivnim testu je preskoc + movzx eax,ah ;vem skip hodnotu do eax + shl eax,2 ;na obrazovce *2 bodu *2 za bod (x8) + add edi,eax ;pricti k edi + lodsb ;vem copy hodnotu + mov cl,al ;zaved counter + xchg esi,ebp ;prohod ukazatele control a data + push ebp ;uchovej control +shwad2: zobraz_2 ;zobraz bod + dec cl ;opakuj tolikrat kolik je copy hodnota + jnz shwad2 + pop ebp ;obnov control + xchg esi,ebp ;prohod ukazatele control a data + jmp shwad3 ;a precti dalsi skip hodnotu +shwad1: pop edx ;obnov registry ukazujici na zacatek radky + pop edi + and ah,03fh ;maskuj spodnich 6 bitu + inc ah ;+1 +shwad4: add edi,640 + dec ch ;odecti counter radek + dec ah ;odecti counter + jnz shwad4 ;a opakuj ah krat + or ch,ch ;je li counter nulovy tak padame + jnz shwad5 + pop ebp ;obnov ebp + ret ;konec + ret + +public klicovani_anm_ + +klicovani_anm_: ;esi source edi target al mirror + or al,al + jnz klicovani_anm_back_ + mov ecx,180 +ka_lp2: mov ebx,320 +ka_lp1: lodsw + movzx eax,ax + test eax,0x8000 + jnz ka_skip + mov edx,eax + shl edx,16 + or eax,edx + mov [edi+1280],eax + mov [edi],eax +ka_skip:add edi,4 + dec ebx + jnz ka_lp1 + add edi,1280 + dec ecx + jnz ka_lp2 + ret + +public klicovani_anm_back_ + +klicovani_anm_back_: ;esi source edi target + mov ecx,180 + add edi,1280 +kba_lp2: mov ebx,320 +kba_lp1: lodsw + sub edi,4 + movzx eax,ax + test eax,0x8000 + jnz kba_skip + mov edx,eax + shl edx,16 + or eax,edx + mov [edi+1280],eax + mov [edi],eax +kba_skip:dec ebx + jnz kba_lp1 + add edi,1280*3 + dec ecx + jnz kba_lp2 + ret + + + + +public small_anm_buff_ ;zobrazi frame v mensim ramecku + +small_anm_buff_: ;ESI - SOURCE + ;EDI - TARGER + ;EBX - PALETA + + mov ecx,179*10000h +shmab4: mov cx,320 +shmab3: zobraz_1 + dec cx + jnz shmab3 + add edi,640 + sub ecx,010000h + jnc shmab4 + ret + +public small_anm_delta_ ;zobrazi frame animace (normal); + + +small_anm_delta_: ;ESI - SOURCE + ;EDI - TARGER + ;EBX - PALETA + + mov ch,180 ;180 radek + mov eax,[esi] ;vem offset na delta data + lea edx,[esi+eax+4] ;ebp obsahuje tento offset + lea esi,[esi+4] ;esi obsahuje offset na delta control +shmad5: push edi ;uchovej zacatek radky +shmad3: lodsb ;vem skip hodnotu + mov ah,al ;uchovej ji ah - kvuli destruktivnimu testu + and al,not 3fh ;na posledni 2 bity + cmp al,0c0h ;C0 a vyssi znamenaji ze se preskakuje radek + jz shmad1 ;pri pozitivnim testu je preskoc + movzx eax,ah ;vem skip hodnotu do eax + shl eax,2 ;na obrazovce *2 bodu *1 zoom *2 za bod (x4) + add edi,eax ;pricti k edi + lodsb ;vem copy hodnotu + mov cl,al ;zaved counter + xchg esi,edx ;prohod ukazatele control a data +shmad2: zobraz_1 ;zobraz bod + zobraz_1 ;zobraz bod + dec cl ;opakuj tolikrat kolik je copy hodnota + jnz shmad2 + xchg esi,edx ;prohod ukazatele control a data + jmp shmad3 ;a precti dalsi skip hodnotu +shmad1: pop edi + and ah,03fh ;maskuj spodnich 6 bitu + inc ah ;+1 +shmad4: add edi,1280 + dec ch ;odecti counter radek + dec ah ;odecti counter + jnz shmad4 ;a opakuj ah krat + or ch,ch ;je li counter nulovy tak padame + jnz shmad5 + ret ;konec + ret + +public scroll_and_copy_ +scroll_and_copy_: ;odscroluje a kopiruje obrazovku do screenu + ;pouzitelne pro titulky + ;0x8000 je transparentni + ;edi screen + ;ebx buffer + ;esi back_picture + ;ecx velikost bufferu (pocet_radku) + ;edx pocet bajtu o kolik je nutne posouvat (*1280) + ;eax - ukazatel na tittle lines + push ebp + mov ebp,eax ;uloz ukazatel na titlelines + mov eax,edx + imul eax,1280 +sac_lp1:push ecx + push eax + mov eax,[ebp] ;nacti zac + mov ecx,[ebp+edx*8] + cmp eax,ecx + jc sac_sk1 + mov eax,ecx +sac_sk1:shl eax,1 ;adresa + add esi,eax ;pricti k pointrum + add edi,eax + add ebx,eax + add ebp,4 ;presun se na kon + shr eax,1 ;eax je zacatek v bodech + mov ecx,[ebp+edx*8] ;vem konec + cmp ecx,[ebp] + jnc sac_sk2 + mov ecx,[ebp] +sac_sk2:push ecx + sub ecx,eax ;kon-zac+1=celk pocet + xchg edx,[esp+4] +sac_lp2:mov eax,[ebx+edx] ;Vem data na dalsim radku + mov [ebx],eax ;Zapis je sem + add ebx,4 ;dalsi pozice + test eax,7fff7fffh ;je to transparentni? + jz sac_all ;pokud ano, zobraz_obrazek + bt eax,15 ;test bitu 15 + jnc sac_1 ;Neni nastaven - zobraz primo barvu + mov ax,[esi] ;jinak vem barvu z obrazku +sac_1: stosw ;zapis barvu + add esi,2 ;dalsi pozice + rol eax,16 ;presun eax na dolni slovo + bt eax,15 ;test bitu 15 + jnc sac_2 ;neni nastaven - zobraz primo barvu + mov ax,[esi] ;jinak vem barvu z obrazku +sac_2: stosw ;zapis barvu + add esi,2 ;dalsi pozice + jmp sac_end +sac_all:movsd ;presun celeho slova +sac_end:sub ecx,2 ;odecti counter + ja sac_lp2 ;je li nad opakuj + add ecx,640 ;pricti sirku, - kolik jsme prejeli + pop eax + sub ecx,eax ;odecti konec -> kolik preskocit + add ebp,4 ;aktualizuj ukazatele + shl ecx,1 ;v adresach + add esi,ecx + add edi,ecx + add ebx,ecx + pop eax + xchg edx,eax + pop ecx ;obnov ecx + dec ecx ;sniz citac radku + jnz sac_lp1 ;dokud neni nula + pop ebp ;obnov ebp + ret ;konec + + + public lodka32_ +lodka32_: + ;esi - zdrojovy blok + ;edi - cil + ;eax - lodka + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + push ebp + mov ebp,eax + mov ebx,_zoom[offset tzoom.ytable] +l32d: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi +l32c: mov eax,dword ptr [ebp] + or eax,eax + jnz l32e + mov al,[edx] + inc edx + or al,al + jz l32a + lodsw + stosw + stosw + jmp l32b +l32e: stosd + movzx eax,byte ptr[edx] ;0 - o 4 1 - o 2 + xor eax,1 ;0->1 1->0 + inc eax ;1+1=2 0+1=1 + shl eax,1 ;2*2=4 1*2=2 + add esi,eax + inc edx + jmp l32b +l32a: lodsd + stosd +l32b: add ebp,4 + dec cx + jnz l32c + pop esi + mov eax,[ebx] + and eax,0ffffh + add esi,eax + add ebx,2 + add edi,_zoom[offset tzoom.textline] + xor cx,cx + cmp ecx,60*65536 + cmc + sbb eax,eax + and eax,1280 + sub ebp,eax + sub ecx,10000h + pop cx + jnz l32d + pop ebp + ret + + public lodka32b_ +lodka32b_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.ytable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;zoom.ycount - interni (ulozeni maskovane adr stranky) + ;zoom.xmax - interni (pocet dwordu do prepnuti) + ;zoom.linelen - interni (velikost stranky v dwordech) + + + call mapvesaadr_ ;mapuj spravne edi + push ebp + mov ebp,eax + mov ebx,_zoom[offset tzoom.ytable] +l32bd: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi + push edi +l32bc: mov eax,dword ptr [ebp] + or eax,eax + jnz l32be + mov al,[edx] + inc edx + or al,al + jz l32ba + lodsw + stosw + stosw + jmp l32bb +l32be: stosd + movzx eax,byte ptr[edx] ;0 - o 4 1 - o 2 + xor eax,1 ;0->1 1->0 + inc eax ;1+1=2 0+1=1 + shl eax,1 ;2*2=4 1*2=2 + add esi,eax + inc edx + jmp l32bb +l32ba: lodsd + stosd +l32bb: add ebp,4 + movzx eax,di ;prevezmi dolni cast edi do eax + dec eax ;odecti 1 (0=0xffffffff) + cmp eax,_gran_mask ;je vetsi nez granualita? + jc l32gb ;ne, vse je ok + mov eax,_lastbank ;ano, pak vem cislo banky + inc eax ;pricti 1 + mov _lastbank,eax ;zapis jako nove cislo banky + pushad ;uchovej vse + call switchvesabank_ ;prepni banku + popad ;obnov vse + mov edi,0a0000h ;vynuluj dolni cast di +l32gb: dec cx ;tady pokracujem + jnz l32bc ;opakuj cxkrat + pop edi ;obnov edi + add di,1280 ;pricti radek + and di,word ptr _gran_mask ;maskuj granualitou + pop esi + mov eax,[ebx] + and eax,0ffffh + add esi,eax + add ebx,2 + xor cx,cx + cmp ecx,60*65536 + cmc + sbb eax,eax + and eax,1280 + sub ebp,eax + sub ecx,10000h + pop cx + jnz l32bd + pop ebp + ret + + + public lodka256_ +lodka256_: + ;esi - zdrojovy blok + ;edi - cil + ;eax - lodka + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;ebx xlat + push ebp + mov ebp,eax +l256d: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi +l256c: mov eax,[ebp] + or eax,eax + jnz l256e + movzx eax,byte ptr [edx] + inc edx + or al,al + jz l256a + lodsw + mov al,[ebx+eax*2] + mov ah,al + stosw + jmp l256b +l256e: movzx eax,ax + mov al,[ebx+eax*2] + mov ah,al + stosw + movzx eax,byte ptr[edx] ;0 - o 4 1 - o 2 + xor eax,1 ;0->1 1->0 + inc eax ;1+1=2 0+1=1 + shl eax,1 ;2*2=4 1*2=2 + add esi,eax + inc edx + jmp l256b +l256a: lodsw + mov al,[ebx+eax*2] + stosb + lodsw + mov al,[ebx+eax*2] + stosb +l256b: add ebp,4 + xor ebx,1 + dec cx + jnz l256c + xor ebx,1 + pop esi + mov edx,_zoom[offset tzoom.ytable] + mov eax,[edx] + and eax,0ffffh + add esi,eax + add edx,2 + mov _zoom[offset tzoom.ytable],edx + add edi,_zoom[offset tzoom.textline] + xor cx,cx + cmp ecx,60*65536 + cmc + sbb eax,eax + and eax,1280 + sub ebp,eax + sub ecx,10000h + pop cx + jnz l256d + pop ebp + ret + + + public lodka256b_ +lodka256b_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.xtable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;ebx xlat + push ebp + mov ebp,eax +l256bd: push cx + mov edx,_zoom[offset tzoom.xtable] + push edi + call mapvesaadr_ + push esi +l256bc: mov eax,[ebp] + or eax,eax + jnz l256be + movzx eax,byte ptr[edx] + inc edx + or al,al + jz l256ba + lodsw + mov al,[ebx+eax*2] + mov ah,al + stosw + jmp l256bb +l256be: movzx eax,ax + mov al,[ebx+eax*2] + mov ah,al + stosw + movzx eax,byte ptr[edx] ;0 - o 4 1 - o 2 + xor eax,1 ;0->1 1->0 + inc eax ;1+1=2 0+1=1 + shl eax,1 ;2*2=4 1*2=2 + add esi,eax + inc edx + jmp l256bb +l256ba: lodsw + mov al,[ebx+eax*2] + stosb +l256bh: lodsw + mov al,[ebx+eax*2] + stosb +l256bb: add ebp,4 + swap_at_end di,edi + xor ebx,1 + dec cx + jnz l256bc + xor ebx,1 + pop esi + pop edi + add edi,640 + mov edx,_zoom[offset tzoom.ytable] + mov eax,[edx] + and eax,0ffffh + add esi,eax + add edx,2 + mov _zoom[offset tzoom.ytable],edx + add edi,_zoom[offset tzoom.textline] + xor cx,cx + cmp ecx,60*65536 + cmc + sbb eax,eax + and eax,1280 + sub ebp,eax + sub ecx,10000h + pop cx + jnz l256bd + pop ebp + ret + + + +_TEXT ends + + +END + + + + + + +if 0 +;POZOR DUMP! + + + public zooming32b_ +zooming32b_: + ;esi - zdrojovy blok + ;edi - cil + ;zoom.xtable - tabulka pro x + ;zoom.ytable - tabulka pro y + ;zoom.textline - rozdil mezi pravym okrajem a levym okrajem + ; pri prechodu na novou radku + ;ecx ysize:xsize + ;zoom.ycount - interni (ulozeni maskovane adr stranky) + ;zoom.xmax - interni (pocet dwordu do prepnuti) + + push ebp + mov ebp,eax + mov ebx,_zoom[offset tzoom.ytable] +z32bd: push cx + mov edx,_zoom[offset tzoom.xtable] + push esi + push edi + call mapvesaadr_ +z32bc: mov al,[edx] + inc edx + or al,al + jz z32ba + lodsw + test ax,8000h + jnz z32be + stosw + stosw + jmp z32bb +z32bf: test eax,8000h + jz z32bg + test eax,80000000h + jz z32bh +z32be: mov eax,[ds:ebp] + stosd + jmp z32bb +z32bg: rol eax,16 + mov ax,[ds:ebp+2] + rol eax,16 + stosd + jmp z32bb +z32bh: mov ax,[ds:ebp] + stosd + jmp z32bb +z32ba: lodsd + test eax,80008000h + jnz z32bf + stosd +z32bb: add ebp,4 + dec cx + jnz z32bc + pop edi + add edi,2048 + pop esi + mov eax,[ebx] + and eax,0ffffh + add esi,eax + add ebx,2 + xor cx,cx + sub ecx,10000h + pop cx + jnz z32bd + pop ebp + ret + +scroll_support_32b_: + ;edi - lbuffer + pozice na obrazovce + ;esi - oldbuffer + ;edx - newbuffer + ;ebx - xlat + ;ecx - size; + push ebp ;uchovej ebp + mov ebp,360 ;ebp pro tuto chvili predstavuje citac + mov eax,ecx ;uchovej ecx jeste v eac - zachova citac sloupcu +scrl1b: push edi + push esi ;uchovej esi + call mapvesaadr_ + shr ecx,1 ;presun ecx bloku + rep movsd + rcl ecx,1 + rep movsw + mov ecx,640 ;dopocitej ecx do 640 + sub ecx,eax + pop esi ;obnov esi + xchg esi,edx ;esi je nyni novy blok + push esi ;uchovek esi + shr ecx,1 ;presun + rep movsd + rcl ecx,1 + rep movsw + pop esi ;obnov esi + xchg esi,edx ;vrat edx a esi do puvodniho stavu + mov ecx,eax ;obnov zase ecx z eax + add esi,1280 ;dalsi radek + add edx,1280 + pop edi + add edi,2048 + dec ebp ; dokud nejsme na konci + jnz scrl1b ;opakuj + pop ebp + ret + +endif diff --git a/GAME/GAMESAVE.C b/GAME/GAMESAVE.C new file mode 100644 index 0000000..8fd4ef6 --- /dev/null +++ b/GAME/GAMESAVE.C @@ -0,0 +1,1586 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +#define STATE_CUR_VER 1 + +#define _GAME_ST "_GAME.TMP" +#define _GLOBAL_ST "_GLOBEV.TMP" +#define _SLOT_SAV "slot%02d.SAV" +#define SLOTS_MAX 10 + +#define GM_MAPENABLE 0x1 + +#define SAVE_SLOT_S 34 +#define LOAD_SLOT_S (372+34) +#define SAVE_SLOT_E (34+203) +#define LOAD_SLOT_E (372+34+203) + +#define SSAVE_VERSION 0 + +static FILE *story=NULL; +static char load_another; +char reset_mobiles=0; + +typedef struct s_save + { + int viewsector; + char viewdir; + short version; + char not_used; + int gold; + short cur_group; + char autosave; + char enable_sort; + char shownames; + char showlives; + char zoom_speed; + char turn_speed; + char autoattack; + char music_vol; + char sample_vol; + char xbass; + char bass; + char treble; + char stereing; + char swapchans; + char out_filter; + long glob_flags; + long game_time; + char runes[5]; + char level_name[12]; + short picks; //pocet_sebranych predmetu v mysi + short items_added; //pocet_pridanych predmetu + int sleep_long; + int game_flags; + }S_SAVE; + +#define ZAKLAD_CRC 0xC005 + +static int get_list_count(); + +static word vypocet_crc(char *data,long delka) + { + unsigned long l=0; + do + { + l=(l<<8)|(delka>0?*data++:0);delka--; + l=(l<<8)|(delka>0?*data++:0);delka--; + l%=ZAKLAD_CRC; + } + while(delka>-1); + return l & 0xffff; + } +static unable_open_temp(char *c) + { + char d[]="Unable to open the file : ",*e; + + concat(e,d,c); + closemode(); + MessageBox(NULL,e,NULL,MB_OK|MB_ICONSTOP); + SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c,0); + exit(1); + } + +static unable_write_temp(char *c) + { + char d[]="Unable to write to the temp file : ",*e; + + concat(e,d,c); + closemode(); + MessageBox(NULL,e,NULL,MB_OK|MB_ICONSTOP); + SEND_LOG("(SAVELOAD) Open temp error detected (%s)",c,0); + exit(1); + } + +void expand_map_file_name(char *s) //prepise *.map na fullpath\*.TMP + { + char *c; + char *st; + c=strchr(s,0); + while (c!=s && *c!='.' && *c!='\\') c--; + if (*c=='.') strcpy(c,".TMP"); + concat(st,pathtable[SR_TEMP],s); + strcpy(s,st); + } + +int load_org_map(char *filename,void **sides,void **sectors,void **coords,int *mapsize) + { + FILE *f; + void *temp; + int sect; + long size,r; + char nmapend=1; + char *c; + + c=find_map_path(filename); + f=fopen(c,"rb");free(c); + if (f==NULL) return -1; + do + { + r=load_section(f,&temp,§,&size); + if (r==size) + switch (sect) + { + case A_SIDEMAP: + *sides=temp; + break; + case A_SECTMAP: + *sectors=temp; + if (mapsize!=NULL) *mapsize=size/sizeof(TSECTOR); + break; + case A_MAPINFO: + if (coords!=NULL) *coords=temp;else free(temp); + break; + case A_MAPGLOB: + //memcpy(&mglob,temp,min(sizeof(mglob),size)); + free(temp); + break; + case A_MAPEND : + nmapend=0; + free(temp); + break; + default: free(temp); + } + else + { + if (temp!=NULL)free(temp); + fclose(f); + return -1; + } + } + while (nmapend); + fclose(f); + return 0; + } + +void save_daction(FILE *f,int count,D_ACTION *ptr) + { + if (ptr!=NULL) + { + save_daction(f,count+1,ptr->next); + fwrite(ptr,1,sizeof(D_ACTION),f); + } + else + fwrite(&count,1,2,f); + } + +void load_daction(FILE *fsta) + { + int i,j; + i=0; + while (d_action!=NULL) //vymaz pripadne delaited actions + { + D_ACTION *p; + p=d_action; d_action=p->next;free(p); + } + fread(&i,1,2,fsta);d_action=NULL; + for(j=0;jnext=d_action; + d_action=p; + } + } + +void save_items(FILE *f) + { + int i,j; + short *c; + + for(i=0;ivyk_max) return -2; + fread(map_vyk,vyk_max,sizeof(TVYKLENEK),fsta); + } + return 0; + } + + +void save_all_fly(FILE *fsta) + { + LETICI_VEC *f; + + f=letici_veci; + fwrite(&f,1,sizeof(f),fsta); + while (f!=NULL) + { + short *c; + fwrite(f,1,sizeof(*f),fsta); + c=f->items; + if (c!=NULL) do fwrite(c,1,2,fsta); while (*c++); + f=f->next; + } + } + +int load_all_fly(FILE *fsta) + { + LETICI_VEC *f=NULL,*n,*p; + p=letici_veci; + while (p!=NULL) {stop_fly(letici_veci,0);p=p->next;} + fread(&f,1,sizeof(f),fsta); + p=letici_veci; + while (f!=NULL) + { + short items[100],*c; + n=New(LETICI_VEC); + c=items;memset(items,0,sizeof(items)); + if (fread(n,1,sizeof(*n),fsta)!=sizeof(*n)) + { + free(n); + if (p!=NULL) p->next=NULL; + return -2; + } + if (n->items!=NULL) + { + do + fread(c,1,2,fsta); + while (*c++); + n->items=NewArr(short,c-items); + memcpy(n->items,items,(c-items)*sizeof(short)); + } + if (p==NULL) p=letici_veci=n;else p->next=n; + p=n; + f=n->next; + n->next=NULL; + } + return 0; + } + + + + +int save_map_state() //uklada stav mapy pro savegame (neuklada aktualni pozici); + { + char sta[200]; + char *bf; + FILE *fsta; + int i; + long siz; + TSTENA *org_sides; + TSECTOR *org_sectors; + short res=-1; + int ver=0; + + restore_sound_names(); + strcpy(sta,level_fname); + expand_map_file_name(sta); + fsta=fopen(sta,"wb");if (fsta==NULL) unable_open_temp(sta); + SEND_LOG("(SAVELOAD) Saving map state for current map",0,0); + if (load_org_map(level_fname,&org_sides,&org_sectors,NULL,NULL)) goto err; + siz=(mapsize+7)/8; + bf=(char *)getmem(siz); + ver=0; + fwrite(&ver,sizeof(ver),1,fsta); //<------------------------- + ver=STATE_CUR_VER; + fwrite(&ver,sizeof(ver),1,fsta); //<------------------------- + fwrite(&mapsize,sizeof(mapsize),1,fsta); //<------------------------- + memset(bf,0,siz); + fwrite(&siz,1,sizeof(siz),fsta); //<------------------------- + for(i=0;i>3]|=1<<(i & 7); + if (!fwrite(bf,siz,1,fsta)) goto err; //<------------------------- + for(i=0;i>3]|=1<<(i & 7); + if (!fwrite(bf,siz,1,fsta)) goto err; //<------------------------- + save_map_description(fsta); + for(i=0;iSTATE_CUR_VER) goto err; + if (!fread(&i,sizeof(mapsize),1,fsta)) goto err; + if (mapsize!=i) goto err; + SEND_LOG("(SAVELOAD) Loading map state for current map",0,0); + fread(&siz,1,sizeof(siz),fsta); + bf=(char *)getmem(siz); + if (!fread(bf,siz,1,fsta)) goto err; + for (i=0;i>3]>>(i & 7)) & 1) map_coord[i].flags|=MC_AUTOMAP; + if (!fread(bf,siz,1,fsta)) goto err; + for (i=0;i>3]>>(i & 7)) & 1) map_coord[i].flags|=MC_DISCLOSED; + } + else + { + if (mapsize!=i) return fclose(fsta); + SEND_LOG("(SAVELOAD) Loading map state for current map",0,0); + fread(&siz,1,sizeof(siz),fsta); + bf=(char *)getmem(siz); + if (!fread(bf,siz,1,fsta)) goto err; + for (i=0;i>3]>>(i & 7)) & 1; + } + load_map_description(fsta); + while (fread(&i,1,2,fsta) && i<=mapsize*4) + if (fread(map_sides+i,1,sizeof(TSTENA),fsta)!=sizeof(TSTENA)) goto err; + while (fread(&i,1,2,fsta) && i<=mapsize) + if (fread(map_sectors+i,1,sizeof(TSECTOR),fsta)!=sizeof(TSECTOR)) goto err; + if (reset_mobiles) //reloads mobiles if flag present + { + char mm[MAX_MOBS]; + for(i=0;i> 1) | (c << 7); + /* + __asm + { + mov al,c + rol al,1; + } + } +*/ +//#pragma aux rotate parm [al] value [al]="rol al,1"; + +/* errors + -1 end of file + 1 disk error + 2 internal error + 3 checksum error + */ +int pack_status_file(FILE *f,char *status_name) + { + int stt; + char rcheck=0; + long fsz; + char *buffer,*c,*fullnam; + word crc; + + SEND_LOG("(SAVELOAD) Packing status file '%s'",status_name,0); + fullnam=alloca(strlen(status_name)+strlen(pathtable[SR_TEMP])+1); + if (fullnam==NULL) return 2; + strcpy(fullnam,pathtable[SR_TEMP]); + strcat(fullnam,status_name); + stt=open(fullnam,O_RDONLY | O_BINARY); + fsz=filelength(stt); + c=buffer=getmem(fsz+12+4+2); + strcpy(c,status_name);c+=12; + *(long *)c=fsz+2; + c+=sizeof(long); + read(stt,c,fsz); + close(stt); + crc=vypocet_crc(c,fsz); + c+=fsz; + memcpy(c,&crc,sizeof(crc)); + fsz+=12+4+2; + rcheck=(fwrite(buffer,1,fsz,f)!=(unsigned)fsz); + free(buffer); + return rcheck; + } + +int unpack_status_file(FILE *f) + { + int stt; + char rcheck=0; + long fsz; + char *buffer,*c,*fullnam; + char name[13]; + word crc,crccheck; + + name[12]=0; + name[11]=0; + fread(name,1,12,f); + SEND_LOG("(SAVELOAD) Unpacking status file '%s'",name,0); + if (name[0]==0) return -1; + fread(&fsz,1,4,f); + c=buffer=(char *)getmem(fsz); + if (fread(buffer,1,fsz,f)!=(unsigned)fsz) return 1; + fullnam=alloca(strlen(name)+strlen(pathtable[SR_TEMP])+2); + if (fullnam==NULL) return 2; + strcpy(fullnam,pathtable[SR_TEMP]); + strcat(fullnam,name); + fsz-=2; + crc=vypocet_crc(c,fsz); + c+=fsz;memcpy(&crccheck,c,sizeof(crccheck)); + if (crc!=crccheck) + { + free(buffer); + return 3; + } + stt=open(fullnam,O_BINARY | O_RDWR | O_CREAT | O_TRUNC, _S_IREAD | _S_IWRITE); + if (stt==-1) + { + free(buffer); + return 1; + } + rcheck=(write(stt,buffer,fsz)!=fsz) ; + free(buffer); + close(stt); + return rcheck; + } + +int pack_all_status(FILE *f) + { + char *c; + WIN32_FIND_DATA inf; + HANDLE res; + + concat(c,pathtable[SR_TEMP],"*.TMP"); + res=FindFirstFile(c,&inf); + if (res!=INVALID_HANDLE_VALUE) + do + { + int i; + if (inf.cFileName[0]!='~') + { + i=pack_status_file(f,inf.cFileName); + if (i) return i; + } + } + while (FindNextFile(res,&inf)); + FindClose(res); + c[0]=0; + fwrite(c,1,12,f); + return 0; + } + +int unpack_all_status(FILE *f) + { + int i; + + i=0; + while (!i) i=unpack_status_file(f); + if (i==-1) i=0; + return i; + } + +int save_basic_info() + { + FILE *f; + char *c; + S_SAVE s; + short *p; + int i; + char res=0; + THUMAN *h; + + concat(c,pathtable[SR_TEMP],_GAME_ST); + SEND_LOG("(SAVELOAD) Saving basic info for game (file:%s)",c,0); + f=fopen(c,"wb"); + if (f==NULL) return 1; + s.viewsector=viewsector; + s.viewdir=viewdir; + s.version=SSAVE_VERSION; + s.not_used=0; + s.gold=money; + s.cur_group=cur_group; + s.shownames=show_names; + s.showlives=show_lives; + s.autoattack=autoattack; + s.turn_speed=turn_speed(-1); + s.zoom_speed=zoom_speed(-1); + s.game_time=game_time; + s.enable_sort=enable_sort; + s.sleep_long=sleep_ticks; + s.sample_vol=get_snd_effect(SND_GFX); + s.music_vol=get_snd_effect(SND_MUSIC); + s.xbass=get_snd_effect(SND_XBASS); + s.bass=get_snd_effect(SND_BASS); + s.treble=get_snd_effect(SND_TREBL); + s.stereing=get_snd_effect(SND_LSWAP); + s.swapchans=get_snd_effect(SND_SWAP); + s.out_filter=get_snd_effect(SND_OUTFILTER); + s.autosave=autosave_enabled; + s.game_flags=(enable_glmap!=0); + strncpy(s.level_name,level_fname,12); + for(i=0;i<5;i++) s.runes[i]=runes[i]; + if (picked_item!=NULL) + for(i=1,p=picked_item;*p;i++,p++);else i=0; + s.picks=i; + s.items_added=item_count-it_count_orgn; + res|=(fwrite(&s,1,sizeof(s),f)!=sizeof(s)); + if (i) + res|=(fwrite(picked_item,2,i,f)!=(unsigned)i); + if (s.items_added) + res|=(fwrite(glob_items+it_count_orgn,sizeof(TITEM),s.items_added,f)!=(unsigned)s.items_added); + res|=save_spells(f); + if (!res) res|=(fwrite(postavy,1,sizeof(postavy),f)!=sizeof(postavy)); + for(i=0,h=postavy;idemon_save!=NULL) + fwrite(h->demon_save,sizeof(THUMAN),1,f); //ulozeni polozek s demony + res|=save_dialog_info(f); + fclose(f); + SEND_LOG("(SAVELOAD) Done... Result: %d",res,0); + return res; + } + +int load_basic_info() + { + FILE *f; + char *c; + S_SAVE s; + int i; + char res=0; + TITEM *itg; + THUMAN *h; + + concat(c,pathtable[SR_TEMP],_GAME_ST); + SEND_LOG("(SAVELOAD) Loading basic info for game (file:%s)",c,0); + f=fopen(c,"rb"); + if (f==NULL) return 1; + res|=(fread(&s,1,sizeof(s),f)!=sizeof(s)); + if (s.game_flags & GM_MAPENABLE) enable_glmap=1;else enable_glmap=0; + i=s.picks; + if (picked_item!=NULL) free(picked_item); + if (i) + { + picked_item=NewArr(short,i); + res|=(fread(picked_item,2,i,f)!=(unsigned)i); + } + else picked_item=NULL; + itg=NewArr(TITEM,it_count_orgn+s.items_added); + memcpy(itg,glob_items,it_count_orgn*sizeof(TITEM)); + free(glob_items);glob_items=itg; + if (s.items_added) + res|=(fread(glob_items+it_count_orgn,sizeof(TITEM),s.items_added,f)!=(unsigned)s.items_added); + item_count=it_count_orgn+s.items_added; + res|=load_spells(f); + for(i=0,h=postavy;idemon_save!=NULL) free(h->demon_save); + if (!res) res|=(fread(postavy,1,sizeof(postavy),f)!=sizeof(postavy)); + for(i=0,h=postavy;iprogramovano=0; + h->provadena_akce=h->zvolene_akce=NULL; + h->dostal=0; + if (h->demon_save!=NULL) + { + h->demon_save=New(THUMAN); + fread(h->demon_save,sizeof(THUMAN),1,f);//obnova polozek s demony + } + } + res|=load_dialog_info(f); + fclose(f); + viewsector=s.viewsector; + viewdir=s.viewdir; + cur_group=s.cur_group; + show_names=s.shownames; + show_lives=s.showlives; + autoattack=s.autoattack; + turn_speed(s.turn_speed); + zoom_speed(s.zoom_speed); + game_time=s.game_time; + sleep_ticks=s.sleep_long; + enable_sort=s.enable_sort; + autosave_enabled=s.autosave; + money=s.gold; + for(i=0;i<5;i++) runes[i]=s.runes[i]; + set_snd_effect(SND_GFX,s.sample_vol); + set_snd_effect(SND_MUSIC,s.music_vol); + set_snd_effect(SND_XBASS,s.xbass); + set_snd_effect(SND_BASS,s.bass); + set_snd_effect(SND_TREBL,s.treble); + set_snd_effect(SND_LSWAP,s.stereing); + set_snd_effect(SND_SWAP,s.swapchans); + set_snd_effect(SND_OUTFILTER,s.out_filter); + if (level_fname==NULL || strncmp(s.level_name,level_fname,12)) + { + strncpy(loadlevel.name,s.level_name,12); + loadlevel.start_pos=viewsector; + loadlevel.dir=viewdir; + send_message(E_CLOSE_MAP); + load_another=1; + } + else load_another=0; + for(i=0;i0) + { + SEND_LOG("(ERROR) Error detected during unpacking game... Loading stopped (result:%d)",r,0); + return r; + } + load_book(); + load_global_events(); + if ((t=load_saved_shops())!=0) return t; + if ((t=load_basic_info())!=0) return t; + running_battle=0; + norefresh=0; + if (!load_another) restore_current_map(); + else + { + save_map=0; + norefresh=1; + } + for(t=0;t0) + { + int xs,ys; + d=c; + while (size && *d!='\r' && *d!='\n') {d++;size--;}; + if (!size) break; + *d=0; + { + char *e,*or; + or=e=getmem(strlen(c)+2); + zalamovani(c,e,STORY_XS,&xs,&ys); + while (*e) + { + str_add(&ls,e); + if (text_width(e)>STORY_XS) abort(); + e=strchr(e,0)+1; + } + c=d+1;size--; + if (*c=='\n' || *c=='\r') {c++;size--;}; + free(or); + } + } + free(text_data); + } + else ls=NULL; + if (story_text!=NULL) release_list(story_text); + story_text=ls; + cur_story_pos=get_list_count();if (cur_story_pos<0) cur_story_pos=0; + redraw_story_bar(cur_story_pos); + } + +static void read_story(int slot) + { + static task_num=-1; + + if (task_num!=-1) term_task(task_num); + if (slot!=-1) + task_num=add_task(8196,read_story_task,slot); + } + + +static int get_list_count() + { + int count,i,max=0; + + if (story_text==NULL) return 0; + count=str_count(story_text); + for(i=0;i0) + { + if (id!=last_select) + { + set_font(H_FBOLD,NORMAL_COLOR); + if (last_select!=-1) place_name(force_save,last_select,1); + set_font(H_FBOLD,SELECT_COLOR); + place_name(force_save,id,1); + last_select=id; + read_story(id); + } + } + else + id=-1; + return id; + } + +char updown_scroll(int id,int xa,int ya,int xr,int yr); + +static char updown_noinst=0; + +static EVENT_PROC(updown_scroll_hold) + { + user_ptr; + WHEN_MSG(E_MOUSE) + { + MS_EVENT *ms; + + ms=get_mouse(msg); + if (ms->event_type==0x4 || !ms->tl1 || ms->tl2 || ms->tl3) + { + send_message(E_DONE,E_MOUSE,updown_scroll_hold); + send_message(E_DONE,E_TIMER,updown_scroll_hold); + updown_noinst=0; + } + } + WHEN_MSG(E_TIMER) + { + MS_EVENT *ms; + + updown_noinst=1; + ms=&ms_last_event; + ms->event_type=0x2; + send_message(E_MOUSE,ms); + if (updown_noinst) + { + send_message(E_DONE,E_MOUSE,updown_scroll_hold); + send_message(E_DONE,E_TIMER,updown_scroll_hold); + updown_noinst=0; + } + else + updown_noinst=1; + } + } + +static char updown_scroll(int id,int xa,int ya,int xr,int yr) + { + int count; + xr,yr,xa,ya; + if (story_text==NULL) return 0; + cur_story_pos+=id; + count=get_list_count(); + if (cur_story_pos>count) cur_story_pos=count; + if (cur_story_pos<0) cur_story_pos=0; + redraw_story_bar(cur_story_pos); + if (updown_noinst) + { + updown_noinst=0; + return 1; + } + send_message(E_ADD,E_MOUSE,updown_scroll_hold); + send_message(E_ADD,E_TIMER,updown_scroll_hold); + return 1; + } + +static char close_saveload(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr;id; + if (ms_last_event.event_type & 0x8) + { + unwire_proc(); + wire_proc(); + } + return 1; + } + +char clk_load_konec(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + send_message(E_CLOSE_MAP,-1); + return 1; + } + +static char clk_load_proc(int id,int xa,int ya,int xr,int yr); + +#define CLK_LOAD_ERROR 5 +T_CLK_MAP clk_load_error[]= + { + {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc,3,H_MS_DEFAULT}, + {-1,30,0,85,14,clk_load_konec,2,H_MS_DEFAULT}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + + +static char clk_load_proc_menu(int id,int xa,int ya,int xr,int yr) + { + id=bright_slot(yr-18); + xa;ya;xr;yr; + if (ms_last_event.event_type & 0x2 && id>=0 && used_pos[id]) + send_message(E_CLOSE_MAP,id); + return 1; + } + +#define CLK_LOAD_MENU 5 +T_CLK_MAP clk_load_menu[]= + { + {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc_menu,3,H_MS_DEFAULT}, + {-1,0,0,639,479,clk_load_konec,8,H_MS_DEFAULT}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + +static char clk_load_proc(int id,int xa,int ya,int xr,int yr) + { + id=bright_slot(yr-18); + xa;ya;xr;yr; + if (ms_last_event.event_type & 0x2 && id>=0 && used_pos[id]) + { + if (load_game(id)) + { + message(1,0,0,"",texty[79],texty[80]); + redraw_load(); + showview(0,0,0,0); + change_click_map(clk_load_error,CLK_LOAD_ERROR); + } + else + { + unwire_proc(); + wire_proc(); + if (battle) konec_kola(); + unwire_proc(); + if (!load_another) + { + wire_main_functs(); + cur_mode=MD_GAME; + bott_draw(1); + pick_set_cursor(); + for(id=0;idmsg==E_KEYBOARD) + { + c=*(char *)msg->data; + if (c==13) + { + send_message(E_KEYBOARD,c); + save_game(slot_pos,global_gamename); + wire_proc(); + read_slot_list(); + msg->msg=-2; + } + else if(c==27) + { + send_message(E_KEYBOARD,c); + msg->msg=-2; + wire_save_load(1); + } + } + } +static char clk_askname_stop(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + if (ms_last_event.event_type & 0x2) + { + send_message(E_KEYBOARD,13); + return 1; + } + else + { + send_message(E_KEYBOARD,27); + return 1; + } + } + + +static void save_it(char ok) + { + if (ok) + { + save_game(slot_pos,global_gamename); + read_slot_list(); + wire_proc(); + GlobEvent(MAGLOB_AFTERSAVE,viewsector,viewdir); + } + else + { + wire_save_load(force_save); + } + } + +#define CLK_ASK_NAME 2 +T_CLK_MAP clk_ask_name[]= + { + {-1,0,0,639,479,clk_askname_stop,8+2,H_MS_DEFAULT}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + + + +void wire_ask_gamename(int id) + { + int x,y; + + x=SAVE_SLOT_S; + y=id*SLOT_SPACE+21+SCREEN_OFFLINE; + slot_pos=id; + schovej_mysku(); + put_picture(x,y,ablock(H_LOADTXTR)); + strcpy(global_gamename,slot_list[id]); + clk_ask_name[0].id=add_task(16384,type_text_v2,global_gamename,x,y,SAVE_SLOT_E-SAVE_SLOT_S,SAVE_NAME_SIZE,H_FBOLD,RGB555(31,31,0),save_it); + change_click_map(clk_ask_name,CLK_ASK_NAME); + ukaz_mysku(); + } + + +#define CLK_SAVELOAD 11 +T_CLK_MAP clk_load[]= + { + {-1,LOAD_SLOT_S,SCREEN_OFFLINE,LOAD_SLOT_E,350,clk_load_proc,3,H_MS_DEFAULT}, + {-1,59,14+SCREEN_OFFLINE,306,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {1,59,310+SCREEN_OFFLINE,306,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {-1,54,378,497,479,start_invetory,2+8,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + + {-1,291,0,313,14,go_book,2,H_MS_DEFAULT}, + {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {1,147,0,205,14,clk_saveload,2,H_MS_DEFAULT}, + {-1,267,0,289,15,clk_sleep,2,H_MS_DEFAULT}, + {-1,0,0,639,479,close_saveload,9,H_MS_DEFAULT}, + }; + + +static char clk_save_proc(int id,int xa,int ya,int xr,int yr) + { + id=bright_slot(yr-18); + xa;ya;xr;yr; + if (ms_last_event.event_type & 0x2 && id>=0) + { + unwire_proc(); + wire_ask_gamename(id); + } + return 1; + } + + +T_CLK_MAP clk_save[]= + { + {-1,SAVE_SLOT_S,SCREEN_OFFLINE,SAVE_SLOT_E,350,clk_save_proc,3,H_MS_DEFAULT}, + {-1,59+274,14+SCREEN_OFFLINE,306+274,46+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {1,59+274,310+SCREEN_OFFLINE,306+274,332+SCREEN_OFFLINE,updown_scroll,2,H_MS_ZARE}, + {-1,54,378,497,479,start_invetory,2+8,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,291,0,313,14,go_book,2,H_MS_DEFAULT}, + {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {0,207,0,265,14,clk_saveload,2,H_MS_DEFAULT}, + {-1,267,0,289,15,clk_sleep,2,H_MS_DEFAULT}, + {-1,0,0,639,479,close_saveload,9,H_MS_DEFAULT}, + }; + +static EVENT_PROC(saveload_keyboard) + { + user_ptr; + WHEN_MSG(E_KEYBOARD) + { + switch (GET_DATA(word)>>8) + { + case 1:unwire_proc();wire_proc();break; + case 'H':if (last_select>0) bright_slot((last_select-1)*SLOT_SPACE+1);break; + case 'P':if (last_select>3]>>(i & 7)) & 1; + load_map_description(fsta); + while (fread(&i,1,2,fsta) && i<=mapsize*4) + if (fread(map_sides+i,1,sizeof(TSTENA),fsta)!=sizeof(TSTENA)) goto err; + while (fread(&i,1,2,fsta) && i<=mapsize) + if (fread(map_sectors+i,1,sizeof(TSECTOR),fsta)!=sizeof(TSECTOR)) goto err; + res=0; + err: + free(bf); + fclose(fsta); + SEND_LOG("(SAVELOAD) Partial restore for map: %s (%s)",level_fname,"DONE"); + return res; + } + + +int load_map_automap(char *mapfile) + { + int i; + + SEND_LOG("(SAVEGAME) CRITICAL SECTION - Swapping maps: %s <-> %s",level_fname,mapfile); + kill_all_sounds(); + for(i=0;i>3)*2048+((g)>>3)*64+((b)>>3)) +#define GET_R_COLOR(col) ((col & 0xF800)>>8) +#define GET_G_COLOR(col) ((col & 0x07E0)>>3) +#define GET_B_COLOR(col) ((col & 0x001F)<<3) + +#define NOSHADOW(x) ((x)|BGSWITCHBIT) + +#define SWAPPATH pathtable[SR_TEMP] +#define TEMP_FILE "~SKELDAL.TMP" +#define PICTURES "..\\OBRAZKY\\" +#define PIC_FADE_PAL_SIZE (10*512+6) + +#define E_REFRESH 256 //udalost refresh scene +#define E_KOUZLO_KOLO 257 //funkce kouzel kazde jedno kolo +#define E_KOUZLO_ANM 258 //funkce kouzel kazdy frame + +//Registracni konstranty +#define H_DESK 0 +#define H_TOPBAR 1 +#define H_OKNO 2 +#define H_KOMPAS 3 +#define H_SIPKY_S 4 +#define H_SIPKY_SV 8 +#define H_SIPKY_SZ 9 +#define H_SIPKY_V 5 +#define H_SIPKY_Z 7 +#define H_SIPKY_J 6 +#define H_BACKMAP 10 +#define H_IOBLOUK 11 +#define H_IDESKA 12 +#define H_IMRIZ1 13 +#define H_RAMECEK 14 +#define H_ENEMY 15 +#define H_FBOLD 16 +#define H_FSYMB 17 +#define H_FLITT 18 +#define H_FLITT5 19 +#define H_FONT6 20 +#define H_FONT7 21 +#define H_FTINY 22 +#define H_FKNIHA 23 +#define H_KOUZLA 24 +#define H_POWERBAR 25 +#define H_POWERLED 26 +#define H_LODKA 27 +#define H_BATTLE_BAR 33 +#define H_BATTLE_MASK 34 +#define H_MZASAH1 35 +#define H_MZASAH2 36 +#define H_MZASAH3 37 +#define H_PZASAH 38 +#define H_BATTLE_CLICK 39 +#define H_SIPKY_END 40 +#define H_LEBKA 41 +#define H_KOSTRA 42 +#define H_KNIHA 43 +#define H_NS_LOGO 44 +#define H_WINTXTR 45 +#define H_SAVELOAD 46 +#define H_SVITEK 47 +#define H_LOADTXTR 48 +#define H_DIALOGY_DAT 49 +#define H_DIALOG 50 +#define H_MS_DEFAULT 51 +#define H_MS_SOUBOJ 52 +#define H_MS_WHO 53 +#define H_MS_LIST 54 +#define H_MS_ZARE 55 +#define H_POSTAVY 60 +#define H_BOTTBAR 66 +#define H_RUNEHOLE 68 +#define H_RUNEMASK 69 +#define H_CHARS 70 +#define H_CHARS_MAX 6 +#define H_POSTAVY_DAT 76 +#define H_SOUND_DAT 77 +#define H_SND_SWHIT1 78 +#define H_SND_SWHIT2 79 +#define H_SND_SWMISS1 80 +#define H_SND_SWMISS2 81 +#define H_SND_SIP1 82 +#define H_SND_SIP2 83 +#define H_SND_KNIHA 84 +#define H_SND_OBCHOD 85 +#define H_SND_LEKTVAR 86 +#define H_SND_TELEPIN 87 +#define H_SND_TELEPOUT 88 +#define H_SND_HEK1M 89 +#define H_SND_HEK2M 90 +#define H_SND_HEK1F 91 +#define H_SND_HEK2F 92 +#define H_SND_EAT 93 +#define H_SND_WEAR 94 +#define H_SND_PUTINV 95 +#define H_RUNEBAR1 100 +#define H_RUNEBAR2 101 +#define H_RUNEBAR3 102 +#define H_RUNEBAR4 103 +#define H_RUNEBAR5 104 +#define H_SPELLDEF 105 +#define H_BUTBIG 106 +#define H_BUTSMALL 107 +#define H_TELEPORT 108 +#define H_XICHTY 112 +#define H_XICHTY_MAX 6 +#define H_DIALOG_PIC 124 +#define H_SHOP_PIC 125 +#define H_SPELL_ANM 127 +#define H_SPELL_WAV 128 +#define H_TELEP_PCX 129 +#define H_TELEP_CNT 14 +#define H_FX 143 +#define H_KILL 144 +#define H_KILL_MAX 10 +#define H_CHECKBOX 154 +#define H_SETUPBAR 155 +#define H_SOUPAK 156 +#define H_SETUPOK 157 +#define H_POSTUP 158 +#define H_LODKA0 159 +#define H_LODKA1 160 +#define H_LODKA2 161 +#define H_LODKA3 162 +#define H_LODKA4 163 +#define H_LODKA5 164 +#define H_LODKA6 165 +#define H_LODKA7 166 +#define H_FLETNA 167 +#define H_FLETNA_BAR 168 +#define H_FLETNA_MASK 169 +#define H_SND_SEVER 170 +#define H_SND_VYCHOD 171 +#define H_SND_JIH 172 +#define H_SND_ZAPAD 173 +#define H_SND_RAND1 174 +#define H_SND_RAND2 175 +#define H_SND_RAND3 176 +#define H_SND_RAND4 177 +#define H_FBIG 178 +#define H_CHARGEN 179 +#define H_CHARGENB 180 +#define H_CHARGENM 181 +#define H_BGR_BUFF 182 +#define H_KREVMIN 183 +#define H_KREVMID 184 +#define H_KREVMAX 185 +#define H_ARMAGED 186 +#define H_ARMA_CNT 13 +#define H_FIRST_FREE 225 +#define H_MENUS_FREE 32768 + +#define MAX_HLAD(x) (((x)->vlastnosti[VLS_MAXHIT]/2+2*24)*HODINA) +#define MAX_ZIZEN(x) (((x)->vlastnosti[VLS_MAXHIT]/3+24)*HODINA) +#define concat(c,s1,s2) \ + c=alloca(strlen(s1)+strlen(s2)+1);\ + strcpy(c,s1);\ + strcat(c,s2) + +#define get_ap(vls) (((vls[VLS_POHYB])>0 && (vls[VLS_POHYB])<15)?1:(vls[VLS_POHYB])/15) + +#define SAVE_NAME_SIZE 32 + +#define mgochrana(x) (100-(x)) +//#define mgochrana(x) (1000/(10+(x))) + +//typy sektoru + +#define ISTELEPORT(c) ((c)==S_TELEPORT || (c)>=S_USERTELEPORT && (c)<=S_USERTELEPORT_END) +#define ISTELEPORTSECT(sect) ISTELEPORT(map_sectors[sect].sector_type) + +#undef S_NORMAL + +#define S_NORMAL 1 +#define S_SCHODY 2 +#define S_SMER 5 +#define S_VODA 9 +#define S_SLOUP 10 +#define S_DIRA 11 +#define S_TELEPORT 12 +#define S_LAVA 4 +#define S_LODKA 3 +#define S_TLAC_OFF 13 +#define S_TLAC_ON 14 +#define S_FLT_SMER 15 +#define S_LEAVE 19 +#define S_VIR 20 +#define S_SSMRT 21 +#define S_ACID 22 +#define S_USERTELEPORT 50 +#define S_USERTELEPORT_END 58 + +//sector flags + +#define MC_AUTOMAP 0x1 //automapovano +#define MC_FLY 0x2 //fly na sektoru +#define MC_PLAYER 0x4 //hrac na sektoru +#define MC_SHADING 0x100 //druhe stinovani (do tmy) +#define MC_DEAD_PLR 0x8 //mrtvy hrac na sektoru +#define MC_DPLAYER (MC_PLAYER | MC_DEAD_PLR) //nejaky hrac na sektoru +#define MC_SPECTXTR 0x10 //specialni textura na sektoru (viz spectxtr) +#define MC_SAFEPLACE 0x20 //bezpecne misto (pod vodou muzou dychat); +#define MC_MARKED 0x80 //oznaceny sektor (pro volne pouziti) +#define MC_DISCLOSED 0x40 //odhaleno kouzlem automapping +#define MC_SHOW_STAIRS 0x200 //obrazek schodu +#define MC_STAIRS_DOWN 0x400 //obrazek schodu dolu (nebo sipka) +#define MC_NOAUTOMAP 0x800 //nelze najit automapingem +#define MC_NOSUMMON 0x1000 //nelze privolat hrace + +//adresare +#define SR_DATA 0 +#define SR_GRAFIKA 1 +#define SR_ZVUKY 2 +#define SR_FONT 3 +#define SR_MAP 4 +#define SR_MUSIC 5 +#define SR_TEMP 6 +#define SR_BGRAFIKA 7 +#define SR_ITEMS 8 +#define SR_ENEMIES 9 +#define SR_VIDEO 10 +#define SR_DIALOGS 11 +#define SR_SAVES 12 +#define SR_WORK 13 +#define SR_CD 14 +#define SR_MAP2 15 +#define SR_ORGMUSIC 16 + +//globalni cisla k casovacum +#define TM_BACK_MUSIC 1 +#define TM_SCENE 2 +#define TM_FAST_TIMER 3 +#define TM_SOUND_RANDOMIZER 4 +#define TM_BOTT_MESSAGE 5 +#define TM_FLY 6 +#define TM_CLEAR_ZASAHY 7 +#define TM_REGEN 8 +#define TM_WAITER 9 +#define TM_SCENE2 10 +#define TM_HACKER 11 +#define TM_FX 12 +#define TM_CHECKBOX 13 +#define TM_FLETNA 14 +#define TM_DELAIER 15 +#define TM_VZPLANUTI 16 + +//umisteni predmetu + +#define PL_NIKAM 0 +#define PL_BATOH 1 +#define PL_TELO_H 2 +#define PL_TELO_D 3 +#define PL_HLAVA 4 +#define PL_NOHY 5 +#define PL_KUTNA 6 +#define PL_KRK 7 +#define PL_RUKA 8 +#define PL_OBOUR 9 +#define PL_PRSTEN 10 +#define PL_SIP 11 + +//hracovi_pozice +#define PO_BATOH 0 +#define PO_TELO_H 1 +#define PO_TELO_D 2 +#define PO_HLAVA 3 +#define PO_NOHY 4 +#define PO_KUTNA 5 +#define PO_KRK 6 +#define PO_RUKA_L 7 +#define PO_RUKA_R 8 + + +//hracovi vlastnosti + +#define VLS_MAX 24 +#define VLS_SILA 0 +#define VLS_SMAGIE 1 +#define VLS_POHYB 2 +#define VLS_OBRAT 3 +#define VLS_MAXHIT 4 +#define VLS_KONDIC 5 +#define VLS_MAXMANA 6 +#define VLS_OBRAN_L 7 +#define VLS_OBRAN_H 8 +#define VLS_UTOK_L 9 +#define VLS_UTOK_H 10 +#define VLS_OHEN 11 +#define VLS_VODA 12 +#define VLS_ZEME 13 +#define VLS_VZDUCH 14 +#define VLS_MYSL 15 +#define VLS_HPREG 16 +#define VLS_MPREG 17 +#define VLS_VPREG 18 +#define VLS_MGSIL_L 19 +#define VLS_MGSIL_H 20 +#define VLS_MGZIVEL 21 +#define VLS_DAMAGE 22 +#define VLS_KOUZLA 23 + + +//rezimy interakce + +#define MD_GAME 0 +#define MD_MAP 1 +#define MD_INV 2 +#define MD_SETUP 3 +#define MD_INBATTLE 4 +#define MD_PRESUN 5 +#define MD_PREZBROJIT 6 +#define MD_UTEK 7 +#define MD_KZ_VYBER 8 +#define MD_END_GAME 9 +#define MD_SHOP 10 +#define MD_ANOTHER_MAP 11 + +//typy map +#define ME_NORMAL 0 //normal map +#define ME_SOPKA 1 //sopka +#define ME_LEDOV 2 //ledove jeskyne +#define ME_PVODA 3 //pod vodou +#define ME_MESTO 4 //nejde sleep (ve meste) + +#define CASE_KEY_1_6 case 2:\ + case 3:\ + case 4:\ + case 5:\ + case 6:\ + case 7 + +typedef struct tdregisters + { + int h_num; + char name[13]; + void (*proc)(void **,long *); + char path; + }TDREGISTERS; + +typedef struct tstena + { + char prim,sec,oblouk,side_tag; + unsigned short sector_tag; + char xsec,ysec; + unsigned long flags; + char prim_anim,sec_anim,lclip,action; + }TSTENA; + +typedef struct tsector + { + char floor,ceil; + char flags,sector_type; //sector_type = 0 - sector not used; + char action,side_tag; + unsigned short step_next[4]; + unsigned short sector_tag; + }TSECTOR; + +typedef struct tvyklenek + { + short sector,dir,xpos,ypos,xs,ys; + short items[9]; + short reserved; + }TVYKLENEK; + + + +typedef TSTENA TSIDEDEF[][4]; +typedef TSECTOR TSECTORDEF[]; + +typedef struct tmap_edit_info + { + short x,y,layer,flags; + }TMAP_EDIT_INFO; + +typedef TMAP_EDIT_INFO TMAP_EDIT[]; + +typedef + struct mapglobal + { + char back_fnames[4][13]; + int fade_r,fade_g,fade_b; + int start_sector; + int direction; + char mapname[30]; + char map_effector; + char local_monsters; + char map_autofadefc; + }MAPGLOBAL; + +typedef struct the_timer + { + int zero; + int id; + int counter,count_max,calls; + void (*proc)(struct the_timer *); + long userdata[4]; + struct the_timer *next; + char zavora; + }THE_TIMER; + +typedef struct d_action + { + unsigned short action,sector,side,flags,nocopy,delay; + struct d_action *next; + }D_ACTION; + +extern word color_topbar[7]; + + +extern MAPGLOBAL mglob; //globalni informace o levelu +extern TSTENA *map_sides; //popisy jednotlivych sten (map_sides[(sector<<2)+dir]) +extern TSECTOR *map_sectors; //popisy sektoru map_sectors[sector] +extern TVYKLENEK *map_vyk; //mapa vyklenku +extern word vyk_max; //pocet vyklenku v mape +extern char *flag_map; //mapa prenasenych flagu +extern TMAP_EDIT_INFO *map_coord; //mapa souradnic a flagu +extern int viewsector; //aktualni sektor vyhledu +extern int viewdir; //aktualni smer vyhledu +extern THE_TIMER timer_tree; //strom casovych udalosti +extern D_ACTION *d_action; //spojovy seznam zpozdenych akci +extern char *pathtable[]; //tabulka adresaru +extern char level_preload; //informace o preloadingu +extern char **texty; //globalni tabulka textu +extern char **level_texts; //lokalni tabulka textu +extern char *level_fname; //jmeno levelu +extern int mapsize; //pocet sektoru v mape +extern int hl_ptr; //ukazatel na konec staticke tabulky registraci +extern int end_ptr; //ukazatel na uplny konec tabulky registraci +extern short **map_items; //ukazatel na mapu predmetu +extern int default_ms_cursor; //cislo zakladniho mysiho kurzoru +extern void *cur_xlat; //aktualni tabulka pro 256 barev +extern void (*unwire_proc)(); //procedura zajistujici odpojeni prave ukoncovane interakce +extern void (*wire_proc)(); //procedura zajistujici pripojeni drive ukoncene interakce +extern char cur_mode; //cislo aktualni interakce +extern word minimap[VIEW3D_Z+1][VIEW3D_X*2+1]; //minimalizovana mapa s informacemi pro sestaveni vyhledu +extern char norefresh; //vypina refresh obrazovky +extern char cancel_render; //okamzite zrusi renderovani sceny na dobu jednoho frame - nastavit na 1 pri zmene interakce!!! +extern char cancel_pass; //okamzite zrusi plynuly prechod +extern char reverse_draw ; //kresba odpredu dozadu +extern char gamespeed; //rychlost hry +extern char gamespeedbattle; //akcelerace rychlosti pro bitvy +extern int num_ofsets[]; //tabulka offsetu pro steny +extern int back_color; //cislo barvy pozadi +extern char cur_group; //cislo aktualni skupiny +extern char group_select; //1 = prave byla sestavena nova skupina +extern unsigned short barvy_skupin[POCET_POSTAV+1]; //cisla barev skupin +extern char battle; //jednicka znaci ze bezi bitva +extern char battle_mode; //rezim bitvy 0=programovani +extern char neco_v_pohybu; //jednicka znaci ze se nektere potvory jeste hejbou +extern short select_player; //vybrana postava nebo -1 +extern char group_sort[POCET_POSTAV]; //pretrideni skupin +extern char global_anim_counter; +extern char one_buffer; //1 zapina pouziti pouze jednoho bufferu pro render +extern char save_map; //1 oznamuje ze pri opusteni levelu je nutne ulozit stav mapy +extern long money; //stav konta hracu +extern long level_map[]; //tabulka urovni +extern char true_seeing; //1 oznamuje ze bezi kouzlo true_seeing +extern char set_halucination; +extern int hal_sector; //cislo sektoru a smeru pri halucinaci +extern int hal_dir; +extern char side_touched; //promena se nastavuje na 1 pri kazdem uspesnem dotyku steny +extern char *texty_knihy; //jmeno souboru s textamy knihy +extern int cur_page; //cislo stranky v knize; +extern long game_time; //hraci cas +extern char autoattack; +extern char enable_sort; +extern char last_send_action; //naposled vyslana akce +extern char see_monster; //jednicka pokud hraci vidi nestvuru +extern char lodka; +extern char anim_mirror; //je li 1 pak animace kouzel a zbrani jsou zrcadlove otocene +extern char insleep; //je li 1 pak bezi sleep +extern char pass_zavora; //je-li 1 pak bezi passing (hraci zrovna jdou) +extern short moving_player; //cislo presouvaneho hrace +extern int bgr_distance; //vzdalenost pozadi od pohledu +extern int bgr_handle; //cislo handle k obrazku pozadi; +extern char enable_glmap; //povoluje globalni mapu; +extern int charmin; +extern int charmax; + +extern int autoopenaction; +extern int autoopendata; + +extern char doNotLoadMapState; + +//debug !!!!! +extern int dhit; +extern int ddef; +extern int ddostal; +extern int dlives; +extern int dmzhit; +extern int dsee; +extern char show_debug; +extern char *debug_text; +extern char map_with_password; +extern int debug_enabled; +extern char marker; //tato promenna je 0, jen v pripade ze je 1 probehne assert +#define MARKER_SET() {SEND_LOG("(MARKER) Marker Sets",0,0);marker=1;} +#define MARKER_RESET() {SEND_LOG("(MARKER) Marker Resets",0,0);marker=0;} +#define MARKER_HIT(action) if (marker) \ + { \ + SEND_LOG("(MARKER) Marker hit!",0,0);\ + action;\ + MARKER_RESET();\ + } + +//builder - skeldal + +int set_video(int mode); +void *game_keyboard(EVENT_MSG *msg,void **usr); +void calc_animations(void); +int load_map(char *filename); +void other_draw(); +void refresh_scene(); +void pcx_fade_decomp(void **p,long *s); +void pcx_15bit_decomp(void **p,long *s); +void pcx_15bit_autofade(void **p,long *s); +void pcx_15bit_backgrnd(void **p,long *s); +void pcx_8bit_decomp(void **p,long *s); +void hi_8bit_correct(void **p,long *s); +void pcx_8bit_nopal(void **p,long *s); +void set_background(void **p,long *s); +void wav_load(void **p,long *s); +void wire_main_functs(); +void ukaz_kompas(); +void *timming(EVENT_MSG *msg,void **data); +void do_timer(); +void hold_timer(int id,char hld); +THE_TIMER *add_to_timer(int id,int delay,int maxcall,void *proc); +void delete_from_timer(int id); +THE_TIMER *find_timer(int id); +void objekty_mimo(); +void mouse_set_cursor(int cursor); +void set_font(int font,int c1,...); +void bott_draw(char); +void bott_draw_proc(); +THE_TIMER *add_to_timer(int id,int delay,int maxcall,void *proc); +void mouse_set_default(int cursor); +void create_frame(int x,int y,int xs,int ys,char clear); +void save_dump(); +void bott_disp_text(char *); +void bott_text_forever(); +char chod_s_postavama(char sekupit); +void hide_ms_at(int line); //schova mysku ktera je nad line +int cislovka(int i); +void wire_kniha(); +void purge_temps(char z); //z=1 vymaze i swapsoubor +void destroy_player_map(); //je nutne volat pred presunem postav +void build_player_map(); //je nutne volat po presunem postav +int postavy_propadnout(int sector); +void postavy_teleport_effect(int sector,int dir,int postava,char eff); +void reg_grafiku_postav(); +void play_movie_seq(char *s,int y); +void check_postavy_teleport(); //je-li viewsector=teleport pak presune postavy + +//builder +#define MAIN_NUM 0 +#define LEFT_NUM 1 +#define RIGHT_NUM 2 +#define CEIL_NUM 3 +#define FLOOR_NUM 4 +#define OBL_NUM 5 +#define OBL2_NUM 6 +#define BACK_NUM 7 + +#define MSG_DELAY (50*10) + + +extern char bott_display; //cislo udava co je zobrazeno v dolni casti +extern int vmode; +extern char runes[5]; + + +typedef struct spectxtr + { + word sector; + word handle; + char count; + char pos; + signed char xpos; + char repeat; + }SPECTXTR; + +#define MAX_SPECTXTRS 64 +typedef SPECTXTR SPECTXT_ARR[MAX_SPECTXTRS]; + +extern SPECTXT_ARR spectxtr; + +void add_spectxtr(word sector,word fhandle,word count,word repeat,integer xpos); +void calc_spectxtrs(void); +void init_spectxtrs(void); +void play_fx(int x,int y); +void draw_fx(); +void play_fx_at(int where); +void draw_blood(char mode,int mob_dostal,int mob_dostal_pocet); + //kresli krev. mode=1 nasaveni, mode=0 kresleni, pri mode=0 se parametry ignoruji + +#define FX_MAGIC 0 +#define FX_BOOK 1 +#define FX_MONEY 2 + + + + +#define BOTT_NORMAL 0 +#define BOTT_TEXT 1 +#define BOTT_FLETNA 2 +#define BOTT_RUNA 3 + + +void step_zoom(char smer); +void turn_zoom(int smer); +void a_touch(int sector,int dir); +int do_action(int action_numb,int sector,int direct,int flags,int nosend); +void delay_action(int action_numb,int sector,int direct,int flags,int nosend,int delay); +long load_section(FILE *f,void **section, int *sct_type,long *sect_size); +void prepare_graphics(int *ofs,char *names,long size,void *decomp,int class); +void show_automap(char full); +void draw_medium_map(); +void anim_sipky(int h,int mode); +void redraw_scene(); +void calc_game(); +void do_delay_actions(); +void real_krok(EVENT_MSG *msg,void **data); +void sort_groups(); +void recheck_button(int sector,char auto_action); +void start_dialog(int entr,int mob); +void show_money(); +void chveni(int i); +void render_scene(int,int); +void bott_draw_fletna(); +void bott_disp_rune(char rune, int item); +extern char noarrows; +void display_ver(int x,int y,int ax,int ay); +void check_players_place(char mode); + + +void add_leaving_place(int sector); +void save_leaving_places(void); +void load_leaving_places(void); +int set_leaving_place(void); +int get_leaving_place(char *level_name); + + +//click_map + +typedef struct t_clk_map + { + int id,xlu,ylu,xrb,yrb; + char (*proc)(int id,int xa,int ya,int xr,int yr); + char mask; + int cursor; + }T_CLK_MAP; + +#define CLK_MAIN_VIEW 17 +#define MS_GAME_WIN 256 +extern T_CLK_MAP clk_main_view[]; //clickovaci mapa pro hlavni vyhled + +void change_click_map(T_CLK_MAP *map,int mapsize); +void ms_clicker(EVENT_MSG *msg,void **usr); +void restore_click_map(void *map,int mapsize); +void save_click_map(void **map,int *mapsize); +void set_game_click_map(void); +void change_global_click_map(T_CLK_MAP *map,int mapsize); +char empty_clk(int id,int xa,int ya,int xr,int yr); //tato udalost slouzi ke zruseni nekterych mist v globalni mape +void disable_click_map(void); + +char start_invetory(int id,int xa,int ya,int xr,int yr); +char go_map(int id,int xa,int ya,int xr,int yr); +char konec(int id,int xa,int ya,int xr,int yr); +char return_game(int id,int xa,int ya,int xr,int yr); +char clk_step(int id,int xa,int ya,int xr,int yr); +char clk_touch(int id,int xa,int ya,int xr,int yr); +char go_book(int id,int xa,int ya,int xr,int yr); +char clk_saveload(int id,int xa,int ya,int xr,int yr); +char clk_sleep(int id,int xa,int ya,int xr,int yr); + + +//inventory viewer - items + +#define IT_ICONE_SIZE (2+2+2+2*256+55*45) +#define MAX_INV 30 +#define HUMAN_PLACES 9 +#define HUMAN_RINGS 4 + +extern int item_count; //pocet predmetu ve hre +extern int it_count_orgn; //puvodni pocet predmetu ve hre (pri loadmap) +extern short water_breath; //vec pro dychani pod vodou +extern short flute_item; + +void load_items(void); +void load_item_map(void *p,long s); +void draw_placed_items_normal(int celx,int cely,int sect,int side); + +#define SPL_INVIS 0x1 //hrac je neviditelny +#define SPL_OKO 0x2 //hrac ma kouzlo oko za oko +#define SPL_TVAR 0x4 //hrac ma kouzlo nastav tvar +#define SPL_DRAIN 0x8 //hrac kazdym utokem drainuje nepritele +#define SPL_MANASHIELD 0x10 //hrac je chranen stitem z many +#define SPL_SANC 0x20 //hraci je kazde zraneni snizeno na polovic +#define SPL_HSANC 0x40 //hrac nikdy nedostane zraneni vetsi nez 18 +#define SPL_BLIND 0x80 //hrac je slepy +#define SPL_REGEN 0x100 //hrac ma regeneraci pri boji +#define SPL_ICE_RES 0x200 //hrac je chranen proti ledu +#define SPL_FIRE_RES 0x400 //hrac je chranen proti ohni +#define SPL_KNOCK 0x800 //knock target back +#define SPL_FEAR 0x1000 //hrac nebo nestvura jsou posedle kouzlem "strach" +#define SPL_STONED 0x2000 //hrac nebo nestvura jsou zkamenele +#define SPL_LEVITATION 0x4000 //hrac nebo nestvura levituji, takze se na ne neuplatnuji nektere efekty sektoru +#define SPL_DEMON 0x8000 //hrac je zmenen v demona + + +#define AC_ATTACK 1 +#define AC_MOVE 2 +#define AC_CANCEL 3 +#define AC_RUN 4 +#define AC_ARMOR 5 +#define AC_STAND 6 +#define AC_MAGIC 7 +#define AC_START 8 +#define AC_THROW 9 + +#define TYP_NESPEC 0 +#define TYP_UTOC 1 +#define TYP_VRHACI 2 +#define TYP_STRELNA 3 +#define TYP_ZBROJ 4 +#define TYP_SVITEK 5 +#define TYP_LEKTVAR 6 +#define TYP_MECH 7 +#define TYP_VODA 7 +#define TYP_JIDLO 8 +#define TYP_SPECIALNI 9 +#define TYP_RUNA 10 +#define TYP_PENIZE 11 +#define TYP_SVITXT 12 +#define TYP_PRACH 13 +#define TYP_OTHER 14 + +#define ITF_DUPLIC 0x8000 //Predmet je duplikaci jineho predmetu +#define ITF_FREE 0x4000 //Predmet byl duplikaci, ted je jeho pozice volna +#define ITF_DESTROY 0x1 +#define ITF_NOREMOVE 0x2 +#define IT_FACES 5 + +#define TPW_MEC 0 +#define TPW_SEKERA 1 +#define TPW_KLADIVO 2 +#define TPW_HUL 3 +#define TPW_DYKA 4 +#define TPW_STRELNA 5 +#define TPW_OST 6 +#define TPW_MAX 7 + +#define TSP_WATER_BREATH 1 //cislo specialni veci pro dychani pod vodou +#define TSP_FLUTE 2 + +#define MAX_SLEEP 4320 + +typedef struct titem + { + char jmeno[32]; //32 Jmeno predmetu + char popis[32]; //64 + short zmeny[24]; //112 Tabulka, jakych zmen ma na hracovy vlastnosti + short podminky[4];//120 Tabulka, jake vlastnosti musi mit hrac k pouziti predmetu + short hmotnost,nosnost,druh; //126 druh = Typ predmetu + short umisteni; //128 Kam se predmet umisti? + word flags; //130 ruzne vlajky + short spell,magie,sound_handle;//136 specialni kouzla / rukojet zvuku + short use_event; //140 specialni udalost + unsigned short ikona,vzhled; //144 ikony a vzhled + short user_value; //146 uzivatelska hodnota + short keynum; //148 cislo klice + short polohy[2][2]; //156 souradnice poloh pro zobrazeni v inv + char typ_zbrane; //160 Typ zbrane + char unused; + short sound; //cislo zvuku + short v_letu[16]; //192 + int cena; + char weapon_attack; //relativni handle k souboru s animaci utok + char hitpos; //pozice zasahu animace + char shiftup; + char byteres; + short rezerva[12]; //224 rezervovane + }TITEM; + +#define PLAYER_MAX_LEVEL 40 + + +typedef struct hum_action + { + short action,data1,data2,data3; + }HUM_ACTION; + + + +typedef struct thuman + { + char used; //1 kdyz je pozice pouzita + char spell; //1 kdyz postava ma na sobe aspon 1 kouzlo. + char groupnum; //cislo skupiny 0-6 + signed char xicht; //cislo obliceje 0-5 + char direction; //smer otoceni + short sektor; //sektor postaveni + short vlastnosti[VLS_MAX]; //mapa aktualnich vlastnosti po korekcich + short bonus_zbrani[TPW_MAX]; //bonusy za zbrane + short lives; //pocet zraneni + short mana; //mnozstvi many + short kondice; //kondice postavy + short actions; //aktualni pocet AP + short mana_battery; //udaj po nabyti nakouzlene many + short stare_vls[VLS_MAX]; //mapa vlastnosti pred korekcemi + short wearing[HUMAN_PLACES]; //nosene predmety + short prsteny[HUMAN_RINGS]; //nosene prsteny + short sipy; //pocet sipu v toulci + short inv_size; //velikost inventare 6-30 + short inv[MAX_INV]; //inventar + short level; //uroven + short weapon_expy[TPW_MAX]; //zkusenosti za zbrane + long exp; //zkusenost + char female; //1 kdyz zena + char utek; //hodnota udavajici pocet kroku pri uteku + HUM_ACTION *zvolene_akce; //ukazatel na tabulku zvolenych akci + HUM_ACTION *provadena_akce; //ukazatel na aktualni akci + char programovano; //pocet programovanych akci + char jmeno[15]; //jmeno + short zasah; //posledni zasah postavy ??? + short dostal; //cislo ktere se ukazuje na obrazku s postavou jako zasah + short bonus; //bonus pro rozdeleni vlastnosti + int jidlo; //max 25000 //pocet kol o hladu zbyvajicich + int voda; //max 20000 //pocet kol o zizny zbyvajicich + struct thuman *demon_save; //ukazatel na postavu ulozenou behem kouzla demon + }THUMAN; + +extern TITEM *glob_items; //tabulka predmetu +extern int ikon_libs; +extern short *picked_item; //retezec sebranych predmetu +extern int item_in_cursor; +extern THUMAN postavy[POCET_POSTAV]; //postavy +extern THUMAN postavy_2[]; //postavy +extern THUMAN *human_selected; //vybrana postava v invetorari +extern int sleep_ticks; +extern int face_arr[IT_FACES]; +char pick_item_(int id,int xa,int ya,int xr,int yr); +void wire_inv_mode(THUMAN *select); +void init_inventory(void); +void init_items(); +void push_item(int sect,int pos,short *picked_item); +void pop_item(int sect,int pos,int mask,short **picked_item); +int count_items_inside(short *place); +int count_items_total(short *place); +char put_item_to_inv(THUMAN *p,short *picked_items); //funkce vklada predmet(y) do batohu postavy +void pick_set_cursor(); //nastavuje kurzor podle vlozeneho predmetu; +void calc_fly(); +void zmen_skupinu(THUMAN *p); +void add_to_group(int num); +void group_all(void); +void build_items_called(void **p,long *s); +void real_regeneration(); //regenerace postav behem hry v realu (pouze kondice a mana) +char sleep_regenerace(THUMAN *p); //regenerace postav behem spani +char check_jidlo_voda(THUMAN *p); +void prepocitat_postavu(THUMAN *human_selected); +void sleep_players(va_list args); //Pozor !!! TASK +void item_sound_event(int item,int sector); +short create_item_money(int obnos); //vytvori predmet penize s urcitym obnosem +char check_map_specials(THUMAN *p); +void destroy_items(short *items); //nici predmety v mysi +void do_items_specs(void); //vola specialni akci predmetu v mysi +short duplic_item(short item); //duplikuje vec a vraci id cislo klonu +int advance_vls(int id); +short create_unique_item(TITEM *it);//vytvari jedinecnou vec pro hru (jako duplikat niceho :-)) +int calculate_weight(THUMAN *p); +int weigth_defect(THUMAN *p); + + + +#define SHP_SELL 0x1 //objekt lze prodat +#define SHP_BUY 0x2 //objekt lze koupit +#define SHP_AUTOADD 0x4 //objekt pribyva casem +#define SHP_SPECIAL 0x8 //objekt se objevi jen obcas +#define SHP_TYPE 0x80 //objekt je popis typu +#define SHP_NOEDIT 0x40 //objekt se nenahrava do editoru. + +typedef struct tproduct + { + short item; //cislo predmetu ktere nabizi + int cena; //cena za jeden + short trade_flags; //vlajky + int pocet; //pocet predmetu na sklade + int max_pocet; + }TPRODUCT; + +typedef struct tshop + { + char keeper[16]; + char picture[13]; + int koef; + int products; + int shop_id; + int list_size; + short spec_max; //maximalni pocet specialnich predmetu + TPRODUCT *list; + }TSHOP; + + +void enter_shop(int shopid); +void load_shops(void); +void reroll_all_shops(); +char save_shops(); +char load_saved_shops(); + +//macros + +#define MAX_ACTIONS 40 +#define MA_GEN 0 +#define MA_SOUND 1 +#define MA_TEXTG 2 +#define MA_TEXTL 3 +#define MA_SENDA 4 +#define MA_FIREB 5 +#define MA_DESTI 6 +#define MA_LOADL 7 +#define MA_DROPI 8 +#define MA_DIALG 9 +#define MA_SSHOP 10 +#define MA_CLOCK 11 +#define MA_CACTN 12 +#define MA_LOCK 13 +#define MA_SWAPS 14 +#define MA_WOUND 15 +#define MA_IFJMP 16 +#define MA_CALLS 17 +#define MA_HAVIT 18 +#define MA_STORY 19 +#define MA_IFACT 20 +#define MA_SNDEX 21 +#define MA_MOVEG 22 +#define MA_PLAYA 23 +#define MA_CREAT 24 +#define MA_ISFLG 25 +#define MA_CHFLG 26 +#define MA_CUNIQ 27 +#define MA_MONEY 28 +#define MA_GUNIQ 29 +#define MA_PICKI 30 +#define MA_WBOOK 31 +#define MA_RANDJ 32 +#define MA_ENDGM 33 +#define MA_GOMOB 34 +#define MA_SHRMA 35 +#define MA_MUSIC 36 +#define MA_GLOBE 37 //global events +#define MA_IFSEC 38 //if sector num +#define MA_IFSTP 39 //if sector type + +#define MAGLOB_LEAVEMAP 0 // v urcitou nastavenou hodinu a minutu dene +#define MAGLOB_STARTSLEEP 1 // postavy maji jit spat. +#define MAGLOB_ENDSLEEP 2 // postavy se probouzi +#define MAGLOB_CLICKSAVE 3 // před otevřením SAVE dialogu +#define MAGLOB_AFTERSAVE 4 // po uložení hry +#define MAGLOB_BEFOREMAGIC 5 // před vyvoláním kouzla +#define MAGLOB_AFTERMAGIC 6 //po vyvolání kouzla +#define MAGLOB_BEFOREMAPOPEN 7 //před otevřením mapy +#define MAGLOB_AFTERMAPOPEN 8 //po uzavření mapy +#define MAGLOB_BEFOREBATTLE 9 //před spuštěním souboje +#define MAGLOB_AFTERBATTLE 10 //po ukončení souboje +#define MAGLOB_BEFOREBOOK 11 //pred otevřením knihy +#define MAGLOB_AFTERBOOK 12 //po uzavření knihy +#define MAGLOB_ONROUND 13 //při každém kole nebo po 10s +#define MAGLOB_ONDEADMAN 14 //při umrtí muže +#define MAGLOB_ONDEADWOMAN 15 //při umrtí ženy +#define MAGLOB_ONDEADALL 16 //při umrtí všech postav +#define MAGLOB_ONHITMAN 17 //při zásahu muže +#define MAGLOB_ONHITWOMAN 18 //při zásahu ženy +#define MAGLOB_ONNEWRUNE 19 //při nalezení nové runy +#define MAGLOB_ONPICKITEM 20 //při sebrání předmětu (pro speciální předměty) +#define MAGLOB_ONSTEP 21 //při kroku (před animaci) +#define MAGLOB_ONTURN 22 //při otočení (před animaci) +#define MAGLOB_ALARM 23 //při spuštění alarmu +#define MAGLOB_ONFIREMAGIC 24 +#define MAGLOB_ONWATERMAGIC 25 +#define MAGLOB_ONGROUNDMAGIC 26 +#define MAGLOB_ONAIRMAGIC 27 +#define MAGLOB_ONMINDMAGIC 28 +#define MAGLOB_ONSPELLID1 29 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID2 30 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID3 31 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID4 32 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID5 33 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID6 34 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID7 35 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID8 36 //při jednom konrétním kouzle +#define MAGLOB_ONSPELLID9 37 //při jednom konrétním kouzle +#define MAGLOB_ONTIMER1 38 //cas - pocet hernich sekund od nastaveni +#define MAGLOB_ONTIMER2 39 //cas - pocet hernich sekund od nastaveni +#define MAGLOB_ONTIMER3 40 //cas - pocet hernich sekund od nastaveni +#define MAGLOB_ONTIMER4 41 //cas - pocet hernich sekund od nastaveni +#define MAGLOB_ONFLUTE1 42 //zahrani urcite melodie +#define MAGLOB_ONFLUTE2 43 //zahrani urcite melodie +#define MAGLOB_ONFLUTE3 44 //zahrani urcite melodie +#define MAGLOB_ONFLUTE4 45 //zahrani urcite melodie +#define MAGLOB_ONFLUTE5 46 //zahrani urcite melodie +#define MAGLOB_ONFLUTE6 47 //zahrani urcite melodie +#define MAGLOB_ONFLUTE7 48 //zahrani urcite melodie +#define MAGLOB_ONFLUTE8 49 //zahrani urcite melodie + +#define MAGLOB_NEXTID 50 //musí být poslední + + + + +#define MC_PASSSUC 0x1 +#define MC_PASSFAIL 0x2 +#define MC_TOUCHSUC 0x4 +#define MC_TOUCHFAIL 0x8 +#define MC_LOCKINFO 0x10 +#define MC_EXIT 0x20 +#define MC_INCOMING 0x40 +#define MC_STARTLEV 0x80 +#define MC_CLOSEDOOR 0x100 +#define MC_ANIM 0x200 +#define MC_ANIM2 0x400 +#define MC_SUCC_DONE 0x800 +#define MC_SPEC_SUCC 0x1000 +#define MC_OPENDOOR 0x2000 +#define MC_VYKEVENT 0x4000 +#define MC_WALLATTACK 0x8000 + +typedef struct tma_gen + { + unsigned action : 6; + unsigned cancel : 1; + unsigned once : 1; + unsigned flags : 16; + }TMA_GEN; + +typedef struct tma_sound + { + char action,flags,eflags; //3 + char bit16; + char volume; //5 + char soundid; //6 + unsigned short freq; //8 + long start_loop,end_loop,offset;//20 + char filename[12]; //32 + }TMA_SOUND; + + +typedef struct tma_text + { + char action,flags,eflags,pflags; + long textindex; + }TMA_TEXT; + +typedef struct tma_send_action + { + char action,flags,eflags,change_bits; + unsigned short sector,side,s_action; + char delay; + }TMA_SEND_ACTION; + +typedef struct tma_fireball + { + char action,flags,eflags; + short xpos,ypos,zpos,speed,item; + }TMA_FIREBALL; + +typedef struct tma_loadlev + { + char action,flags,eflags; + short start_pos; + char dir; + char name[13]; + }TMA_LOADLEV; + + + +typedef struct tma_dropitm + { + char action,flags,eflags; + short item; + }TMA_DROPITM; + +typedef struct tma_codelock + { + char action,flags,eflags; + char znak; + char string[8]; + char codenum; + }TMA_CODELOCK; + +typedef struct tma_cancelaction + { + char action,flags,eflags,pflags; + short sector,dir; + }TMA_ACTN; + +typedef struct tma_swapsectors + { + char action,flags,eflags,pflags; + short sector1,sector2; + }TMA_SWAPS; + +typedef struct tma_wound + { + char action,flags,eflags,pflags; + short minor,major; + }TMA_WOUND; + + + +typedef struct tma_lock + { + char action,flags,eflags; + short key_id; + short thieflevel; + }TMA_LOCK; + +typedef struct tma_two_parms + { + char action,flags,eflags; + short parm1,parm2; + }TMA_TWOP; + +typedef struct tma_create_unique + { + char action,flags,eflags; + TITEM item; + }TMA_UNIQUE; + +typedef struct tma_globe + { + char action,flags,eflags,event; //event - MAGLOB_XXXX + unsigned short sector; //sektor of action target, when event occured + unsigned char side; //side of action target, when event occured + unsigned char cancel; //1 - cancel event + unsigned long param; //event depend param - zero is default + }TMA_GLOBE; + + +typedef struct tma_ifsec +{ + char action,flags,eflags; + unsigned char side; //side of action target, when event occured + unsigned short sector; //sektor of action target, when event occured + short line; //jump line + char invert; //invert condition +}TMA_IFSEC; + + + +extern TMA_LOADLEV loadlevel; + +typedef union tmulti_action + { + struct tma_gen general; + struct tma_sound sound; + struct tma_text text; + struct tma_send_action send_a; + struct tma_fireball fireball; + struct tma_loadlev loadlev; + struct tma_dropitm dropi; + struct tma_codelock clock; + struct tma_cancelaction cactn; + struct tma_lock lock; + struct tma_swapsectors swaps; + struct tma_wound wound; + struct tma_two_parms twop; + struct tma_create_unique uniq; + struct tma_globe globe; + struct tma_ifsec ifsec; + }TMULTI_ACTION; + +extern int **macros; //tabulka maker +extern void *macro_block; //alokovany blok maker (pri unloadu free!) +extern int macro_block_size; //velikost bloku; + +void load_macros(int size,void *data); +void call_macro(int side,int flags); +void call_macro_ex(int side,int flags, int runatsect); +char get_player_triggered(int p); //zjistuje zda hrac s cislem p byl makrem zasazen; +char save_load_trigger(short load); //uklada/obnovuje trigger vlajky. -1 uklada, jinak hodnota ulozeneho triggeru +char save_codelocks(FILE *fsta); //uklada do savegame nastaveni kodovych zamku (128 bytu); +char load_codelocks(FILE *fsta); //obnovuje ze savegame nastaveni kodovych zamku (128 bytu); + + +typedef struct letici_vec + { + struct letici_vec *next; + int sector,smer; + int xpos,ypos,zpos; + short item; + short *items; + int counter; + char anim_pos; + char flags; + short owner; + int speed; + int velocity; + short hit_bonus; + short damage; + short lives; + }LETICI_VEC; + + +extern LETICI_VEC *letici_veci; //spojovy seznam leticich veci +extern LETICI_VEC *letici_veci2; //spojovy seznam leticich veci aktualni pred zahajenim renderace +#define FLY_NEHMOTNA 1 //leti rovne +#define FLY_DESTROY 2 //znici se +#define FLY_DESTROY_SEQ 4 //bezi nicici sekvence +#define FLY_NEDULEZITA 8 //nema vliv na souboj +#define FLY_IN_FLY 16 //Nastaveno, pokud fly ma vliv na okoli (v letu) +#define FLY_BURNT 32 //vyhorela - bude uvolnena +#define FLY_UNUSED 64 //nevyuzita - muze byt uvolnena +#define TFLY LETICI_VEC +LETICI_VEC *throw_fly(int x,int y, char rovne); + +/* postup pri niceni fly + +Pri triggeru zniceni + 1) Je Destroy? - > nastav DESTROY_SEQ + 2) Po zniceni -> nastav BURNT + 3) Pokud je pri zpracovani BURNT -> nastav UNUSED + 4) Pokud je unused -> vymaz ji + +Tento slozity postup je zaveden, z duvodu viceulohoveho zpracovani, aby mel +system jistotu ze vsechny pripadne kopie fly jsou znicene a neukazuji + na neplatne objekty + + Zkratka - pokud je fly znicena, musi ji system potvrdit jeste vlajkou UNUSED, aby + ji mohl uvolnit + */ + +LETICI_VEC *create_fly(); //vytvari fly - optimalizuje tim ze hleda nevyuzity fly nosice, a teprve pokud neuspeje alokuje novy prostor. +void draw_fly_items(int celx,int cely,int sector,int side); +void add_fly(LETICI_VEC *p); +void build_fly_map(); +void destroy_fly_map(); +void stop_fly(LETICI_VEC *p,char zvuk); + + + +//gamesaver +void leave_current_map(); +int save_map_state(); //uklada stav mapy pro savegame (neuklada aktualni pozici); +int load_map_state(); //obnovuje stav mapy; nutno volat po zavolani load_map; +void restore_current_map(); //pouze obnovuje ulozeny stav aktualni mapy +int load_game(int slotnum); +int save_game(int slotnum,char *gamename); +void wire_save_load(char save); +#define autosave() if (autosave_enabled) save_game(9,"AUTOSAVE"); +extern char autosave_enabled; +int load_map_automap(char *mapfile); + /* ^^^ Tato funkce zmeni mapu, bez zmeny grafiky a stavu cele hry. + Jeji vyuziti je pro zobrazeni automapingu jineho levelu nez aktualniho + Pred navratem do hry je treba udelat load_map_automap(level_fname);!!!*/ + +//setup +char q_runsetup(char *); +void user_setup(); +void setup_dialoge(); +char game_setup(int id,int xa,int ya,int xr,int yr); +void GamePause(); +void show_textured_button(int x,int y,int xs,int ys,int texture,void *border3d); + +//sounder & music + +extern short sample_volume; //hlastitost samplu +extern char **sound_table; + +void init_tracks(); +void recalc_volumes(int sector,int side); +void play_effekt(int x,int y,int xd,int yd,int side,int sided,TMA_SOUND *p); +void create_playlist(char *playlist); +void play_next_music(char **c); +void purge_playlist(); +void restore_sound_names(); +void play_sample_at_sector(int sample,int sector1,int sector2,int track, char loop); +void play_sample_at_channel(int sample,int channel,int vol); +void stop_track(int track); +char test_playing(int track); +void stop_track_free(int track); +void mute_all_tracks(char all); +void kill_all_sounds(); +void create_sound_table(char *template,long size); +void create_sound_table_old(); +void start_play_flute(); +void stop_play_flute(); +void pc_speak_play_sample(char *sample,int size,char step,int freq); +char enable_sound(char enbl); + + +//enemy +#define MOBS_INV 16 +#define MOB_POSIT 0 +#define MOB_ATTACK 1 +#define MOB_TOHIT 2 + +#define MAX_MOBS 255 + + +#define MOB_IN_BATTLE 0x1 +#define MOB_ATTACKING 0x2 +#define MOB_TO_HIT 0x4 +#define MOB_DEATH 0x5 +#define MOB_START 1 + +#define MOB_WALK 0x1 +#define MOB_WATCH 0x2 +#define MOB_LISTEN 0x4 +#define MOB_BIG 0x8 +#define MOB_GUARD 0x10 +#define MOB_PICK 0x20 +#define MOB_PICKING 0x40 +#define MOB_ROGUE 0x80 +#define MOB_SENSE 0x4 +#define MOB_PASSABLE 0x2 +#define MOB_MOBILE 0x8 +#define MOB_RELOAD 0x10 +#define MOB_SAMPLE_LOOP 0x40 +#define MOB_LIVE 0x80 //potvora zije +#define MOB_CASTING 0x20 + +typedef struct tmob + { + char name[30]; //jmeno moba + short casting; + short adjusting[6*16]; //volba stredu pro animace + word sector,dir; //pozice + char locx,locy; //presna pozice + char headx,heady; //pozice kam mob miri + short anim_counter; //citac animaci + short vlastnosti[24]; //zakladni vlastnosti potvory + short inv[MOBS_INV]; //batoh potvory + short lives; //pocet zivotu potvory + short cislo_vzoru; //informace urcujici ze ktereho vzoru byl mob vytvoren + short speed; //rychlost pohybu + short dohled; //kam dohl‚dne + short dosah; //okam‘ik za‡ tku souboje + char stay_strategy; //chovani moba ve statickem modu (nepronasleduje) + char walk_data; //cislo potrebne pro pohyb moba v bludisti + word bonus; //bonus za zabiti + char flee_num; //pravdepodobnost uteku + char anim_counts[6]; //pocet animacnich policek pro kazdy pohyb + char mobs_name[7]; //zaklad jmena souboru pro moba + long experience; //zkusenost + char vlajky; //BIT0 - 1 v boji + char anim_phase; //cinnost kterou mob dela + short csektor; //Cilovy sektor + short home_pos; //domaci pozice + short next; //Cislo dalsiho moba, ktery stoji na jeho pozici + char actions; //pocet akci ktere muze potvora provest v kole + char hit_pos; //animacni pozice, kdy potvora zasahne + word sounds[4]; //zvuky z listu + signed char palette; // pocet pouzitelnych palet / cislo palety + char mode; //akce potvory + short dialog; //cislo dialogu, -1 kdyz neni; + char dialog_flags; //vlajky mapovane do dialogu; + word money; //penize + word specproc; //specproc + word dostal; //pocet zivotu, ktere mu byly ubrany poslednim zasahem + char user_data; //data uzivatelem definovane - treba pro spec. + }TMOB; + + +extern TMOB mobs[MAX_MOBS]; +extern char *mob_map; + +void draw_mob(int num,int curdir,int celx,int cely,char shiftup); +void calc_mobs(); +void najdi_cestu(word start,word konec,int flag,word **cesta, int aimbig); +void sirit_zvuk(word start); +void check_all_mobs(); +void build_all_players(); +void init_mobs(); +void refresh_mob_map(); +char akce_moba_zac(TMOB *m); +void mob_animuj(); //animuje prave bojovou akci potvor na sektoru +void sleep_enemy(char regen); +int vyber_potvoru(int sect,int dir,int *z); +void mob_hit(TMOB *mm,int dostal); +int mob_alter(int sect); +void check_all_mobs_battle(); //kontroluje zda je nekdo v battle +void manashield_check(short *vls,short *lives,short *mana,int dostal); +char track_mob(int sect,int dir);//trackuje pritomnost potvory v urcitem smeru +void stop_all_mobs(); +int utok_na_sektor(THUMAN *p,TMOB *m,int chaos,int bonus); +int vyber_potvoru(int sect,int dir,int *chaos); //vybere potvoru ze sektoru a smeru. Vraci take pocet potvor v promenne *chaos +void load_enemies(short *data,int size,int *grptr,TMOB *template,long tsize); +char mob_test_na_bitvu(TMOB *p); //nastavi p->vlajky|MOB_INBATTLE pokud potvora muze vstoupit do bitvy; +void send_mob_to(int m,word *path); +void save_enemy_paths(FILE *f); +int load_enemy_paths(FILE *f); +void regen_all_mobs(); + + +//souboje +extern int mob_dostal; // ikona pro zasah moba +extern int mob_dostal_pocet; // ciselna hodnota toho kolik mob dostal; +extern short vybrana_zbran; //zbran_kterou utoci select_player; +extern char mute_hit_sound; //nastavit, pokud je nutne zabranit zvuku vzdechy, automaticky se resetuje +extern int hromadny_utek; //1 postavy utikaji hromadne. + +extern char running_battle; + +#define MAX_WEAPON_SKILL 10 + +void zacni_souboj(TMOB *p,int delka,short sector); +char q_zacit_souboj(TMOB *p,int d,short sector); +void stop_mob(TMOB *p); +void start_battle(); +int vypocet_zasahu(short *utocnik,short *obrance, int chaos,int zbran,int bonusplus); +void rozhodni_o_smeru(TMOB *p); +void krok_moba(TMOB *p); +void pomala_regenerace_postavy(THUMAN *p); +char zasah_veci(int sector,TFLY *fl); +void vymaz_zasahy(THE_TIMER *q); +char check_end_game(); +void wire_end_game(); +void auto_group(); +void wire_fly_casting(int i); +void konec_kola(); +void send_experience(TMOB *p,int dostal); +void send_weapon_skill(int druh); +void check_player_new_level(THUMAN *p); +void poloz_vsechny_predmety(); +char player_check_death(THUMAN *p, char afterround); //pokud je battle, nezabije postavu, ale az po skonceni kola (afterround==1) +char player_hit(THUMAN *p,int zraneni,char manashield); +void enforce_start_battle(); +void pozdrz_akci(); +void uprav_podle_kondice(THUMAN *p,int *chaos); //upravi parametr chaos podle kondice pro obranu +THUMAN *isplayer(int sector,THUMAN *h,char death); + /* Vraci nasledujiciho hrace na sektoru. Pokud je h==NULL vraci prvniho. + pokud je vysledek NULL neni dalsiho hrace + Death=1 pocita i mrtvoly + */ +int trace_path(int sector,int dir); //zjistuje zda je mozne strilet + + +int numplayers(int sector,char death); + /* Vraci pocet hracu na sektoru, death=1 pocita i mrtvoly */ +TMOB *ismonster(int sector,TMOB *m); + /* Vraci dalsi nestvuru na sektoru, pokud je m==NULL vraci prvni. + Pokud je vysledek NULL neni nestvura na sektoru*/ + +void correct_level(); + + + +//kouzla +extern char running_anm; +extern short teleport_target; +extern char hlubina_level; +extern word *anim_render_buffer; +extern char spell_cast; //0=neni rezim vyberu kouzla; + +#define isdemon(p) ((p)->stare_vls[VLS_KOUZLA] & SPL_DEMON) + + +void kouzla_init(); +void test_play(int handle); +void cast(int num,THUMAN *p,int owner,char backfire); +int add_spell(int num,int cil,int owner,char noanim); +void klicovani_anm(void *target,void *source,char mirror); +//#pragma aux klicovani_anm parm [edi][esi][eax] modify [ecx edx ebx] +int get_spell_color(THUMAN *p,int num); +int get_spell_mana(int num); +int get_spell_um(int num); +char ask_who(int num); +void display_spell_in_icone(int handle,int xicht); +void reinit_kouzla_full(); +char get_rune_enable(THUMAN *p,int strnum); +void remove_all_mob_spells(); +int save_spells(FILE *f); +int load_spells(FILE *f); +char get_spell_track(int num); +void mob_cast(int num,TMOB *m,int mob_num); +void thing_cast(int num,int postava,int sector,TMOB *victim,char noanim);//vyvolavaji veci +void area_cast(int num,int sector,int owner,char noanim); +int select_teleport_target(); +char get_spell_teleport(int num); +void spell_throw(int cil,int what); //to je procedura ktera umoznuje potvoram strilet +void play_big_mgif_animation(int block); +void unaffect_demon(int cil); //ukonci demona pri jeho smrti +char *get_rune_name(int strnum); +void spell_sound(char *name); + + +//interface +#define WINCOLOR RGB555(24,24,24) // 11000 11000 0 11000 +#define BAR_COLOR RGB555(15,13,11) +#define SETUP_COL1 RGB555(20,31,20) +#define SETUP_COL2 RGB555(31,31,12) +#define S_WINPOS_X 100 +#define S_WINPOS_Y 100 +#define S_WINPOS_XS 320 +#define S_WINPOS_YS 300 + +typedef struct enc_file + { + FILE *f; + char *to_delete; + }ENCFILE; + +void add_window(int x,int y,int xs,int ys,int texture,int border,int txtx,int txty); +int message(int butts,char def,char canc,char *keys,...); +void type_text(); //event procedura (parms: X,Y,TEXT,MAX_SPACE,MAX_CHARS); +void type_text_v2(va_list args);//char *text_buffer,int x,int y,int max_size,int max_chars,int font,int color,void (*exit_proc)(char)); +void zalamovani(char *source,char *target,int maxxs,int *xs,int *ys); +void col_load(void **data,long *size); +void open_story_file(); +void write_story_text(char *text); +void close_story_file(); +char labyrinth_find_path(word start,word konec,int flag,char (*proc)(word),word **cesta); + //tato procedura je obecne hledani cesty. Start - startovni cislo sektoru + //Konec - cilove cislo sektoru + //flag - je podminkovy flag pro nepruchozi steny + //proc - je procedura volana pro kazdy sektor + //cesta - je ukazatel na ukazatel na vyslednou cestu + //pokud je cesta=NULL pak vraci pouze zda cesta existuje ci nikoliv +void radio_butts_gr(); +void start_check(); //testuje stav pocitace a rozhodne zda lze program spustit +void check_number_1phase(char *exename); //check serial number! Task!// +void animate_checkbox(int first_id,int last_id,int step); +void fletna_pridej_notu(char note); +void check_fletna(); +char fletna_get_buffer_pos(); +void check_global_fletna(); +void fletna_glob_add_note(char note); + + +char *find_map_path(char *filename); //vyhledava jmeno mapy v alternativnich cestach. + //Vysledny retezec je nutne uvolnit (free) ! +FILE *enc_open(char *filename,ENCFILE *fil); //dekoduje a otevira TXT soubor (ENC) +void enc_close(ENCFILE *fil); //uzavira dekodovany soubor. +int load_string_list_ex(char ***list,char *filename); + +int smlouvat_nakup(int cena,int ponuka,int posledni,int puvod,int pocet); +int smlouvat_prodej(int cena,int ponuka,int posledni,int puvod,int pocet); +int smlouvat(int cena,int puvod,int pocet,int money,char mode); + +void disable_intro(); +void show_jrc_logo(char *filename); + + +//dialogy +void call_dialog(int entr,int mob); +char save_dialog_info(FILE *f); +char load_dialog_info(FILE *f); +short *q_item_one(int i,int itnum); //test zda postava i ma vec itnum +short *q_item(int itnum,int sector); //test zda-li aspon jeden na sectoru ma vec itnum +void change_flag(int flag,char mode); //meni vlajku = 0 - reset, 1 - set, 2 - neg +char test_flag(int flag); //vraci stav vlajky; + + + +//generator +char enter_generator(); + +//kniha +#define add_to_book(odst) add_text_to_book(texty_knihy,odst) +void add_text_to_book(char *filename,int odst); +void write_book(int page); +int count_pages(); +void save_book(); +void load_book(); +void prekodovat(char *c); + + +//menu +int enter_menu(char open); //task! +void titles(va_list args); //task! +void run_titles(va_list args); //task! +void effect_show(va_list args); //effektni zobrazeni // task! +void konec_hry(); + + +//globmap +void wire_global_map(); +void wire_automap_file(char *mapfile); +char set_select_mode(char mode); + +void PodporaStitu(THUMAN *h, short *vlastnosti); + +typedef struct _tag_globalEventDef +{ + unsigned short sector; //sektor of action target, when event occured + unsigned char side; //side of action target, when event occured + unsigned char cancel; // + long param; //event depend param - zero is default +}SGlobalEventDef; + +extern SGlobalEventDef GlobEventList[MAGLOB_NEXTID]; + +static __inline char GlobEvent(int event, int sector, int side) +{ + if (GlobEventList[event].sector || GlobEventList[event].side) + call_macro_ex(sector*4+side,MC_INCOMING,GlobEventList[event].sector*4+GlobEventList[event].side); + return !GlobEventList[event].cancel; +} + + +static __inline char GlobEvents(int firstevid, int lastevid, int sector, int side, long param) +{ + int i; + for (i=firstevid;i<=lastevid;i++) if (GlobEventList[i].param==param) + { + return GlobEvent(i,sector,side); + } + return 1; +} + + +static __inline char TimerEvents(int sector, int side, long time) +{ + int i; + for (i=MAGLOB_ONTIMER1;i<=MAGLOB_ONTIMER4;i++) if (GlobEventList[i].param && GlobEventList[i].param<=time) + { + GlobEventList[i].param=0; + return GlobEvent(i,sector,side); + } + return 1; +} + +//extras +#include "extras.h" diff --git a/GAME/GLOBMAP.C b/GAME/GLOBMAP.C new file mode 100644 index 0000000..42f6271 --- /dev/null +++ b/GAME/GLOBMAP.C @@ -0,0 +1,662 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" + +#define GLOBMAP "GLOBMAP.DAT" + +#define ODDELOVACE ";:=,\n{}" +#define OD_COMMAND oddelovace[0] +#define OD_CRIT oddelovace[1] +#define OD_SET oddelovace[2] +#define OD_COMMA oddelovace[3] +#define OD_NEWLINE oddelovace[4] +#define OD_IN oddelovace[5] +#define OD_OUT oddelovace[6] +#define OD_COMMENT '`' + +#define INDEXU 256 + +typedef struct index_def + { + char mapname[13]; + char *text; + char defined; + }INDEX_DEF; + +static INDEX_DEF *index_tab=NULL; +static char last_index=1; + +static int usemap; + +static FILE *glbm; +static char oddelovace[]=ODDELOVACE; +static last_oddelovac; +static linecounter=0; +static int enter_sector=0; +static char *symbolmap[]= + { + "A !", + "B &&", + "D BREAK", + "O CURMAP", // krit + "E DRAW", + "F ESCAPE", + "G FLG", // krit + "P IFDEF", // krit + "I INDX", + "I INDEX", + "K MAP", + "Q SEKTOR", // krit + "Q SECTOR", // krit + "L TEXT", + "M UNDEF", + "N USEMAP", + "C ||", + }; + +#define OP_NOT 'A' +#define OP_AND 'B' +#define OP_OR 'C' +#define OP_INDX 'I' +#define OP_DRAW 'E' +#define OP_TEXT 'L' +#define OP_MAP 'K' +#define OP_UNDEF 'M' +#define OP_FLG 'G' +#define OP_USEMAP 'N' +#define OP_BREAK 'D' +#define OP_ESCAPE 'F' +#define OP_CURMAP 'O' +#define OP_ISDEF 'P' +#define OP_SEKTOR 'Q' + +#define ODD last_oddelovac + +static char cti_int_num(int *readed) + { + return !fscanf(glbm,"%d",readed); + } + +static int find_symbol(char **symbolmap,int list_len,int offset,char *symbol) + { + int start_pos; + char chr=0; + + start_pos=0; + while (start_pos*symbol) return -1; + if (chr && ss[offset-1]!=chr) return -1; + start_pos++; + } + if (*symbol) return -1; + return start_pos; + } + +static char get_symbol(char *symb) + { + int i; + + i=find_symbol(symbolmap,sizeof(symbolmap)/sizeof(char *),2,symb); + if (i==-1) return 0;else return symbolmap[i][0]; + } + +static int cti_oddelovac(void)//cte prvni oddelovac - preskakuje mezery + { + int c; + do + { + c=getc(glbm); + if (c==OD_COMMENT) while((c=getc(glbm))!='\n'); + if (c=='\n') linecounter++; + if (strchr(oddelovace,c)!=NULL || c==EOF) return c; + } + while (c==' ' || c=='\x9'); + ungetc(c,glbm); + return 0; + } + +static int cti_retezec(int znaku,char *text,char mezera,char upcase) + { + int c; + + znaku--; + if (mezera) + { + while((c=getc(glbm))==32 || c==9); + } + else c=getc(glbm); + while (strchr(oddelovace,c)==NULL && ((c!=32 && c!=9) || !mezera) && c!=EOF) + { + if (upcase) c=toupper(c); + if (znaku) + { + *text++=c; + znaku--; + } + c=getc(glbm); + } + if (c!=32 && c!=9) ungetc(c,glbm); + *text=0; + return 0; + } + +static void error(char *text) + { + char popis[300]; + + sprintf(popis,"Chyba v souboru "GLOBMAP" na radce %d.\r\n%s",linecounter,text); + SEND_LOG("(ERROR) %s : %s",popis,text); + closemode(); + MessageBox(NULL,popis,NULL,MB_OK|MB_ICONSTOP); + exit(0); + } + +static void ex_error(char znak) + { + char ex_text[100]; + + sprintf(ex_text,"Ocekava se znak '%c'",znak); + error(ex_text); + } + +static void ready_index_tab(void) + { + index_tab=NewArr(INDEX_DEF,INDEXU); + memset(index_tab,0,INDEXU*sizeof(INDEX_DEF)); + } + +static void purge_index_tab(void) + { + if (index_tab) + { + int i; + for(i=0;i<255;i++) if (index_tab[i].text!=NULL) free(index_tab[i].text); + free(index_tab); + index_tab=NULL; + } + } + +static char test_kriterii(void) + { + char last_op=0; + char not_op=0; + char text[128]; + char hodn; + char vysl=0; + char symb,*c; + + while (ODD==0 || ODD==OD_NEWLINE) + { + cti_retezec(100,text,1,1); + c=text;if (*c=='!') not_op=1,c++; + symb=get_symbol(c); + switch (symb) + { + case OP_AND:last_op=1;break; + case OP_NOT:not_op=!not_op;break; + case OP_OR:last_op=0;break; + case OP_SEKTOR: + { + int c; + if (cti_int_num(&c)) error("O‡ek v  se ‡ˇslo"); + hodn=c==enter_sector; + } + break; + case OP_CURMAP:cti_retezec(100,text,1,1); + hodn=!strcmp(level_fname,text); + break; + case OP_ISDEF:{ + int c; + if (cti_int_num(&c)) error("O‡ek v  se ‡ˇslo"); + hodn=index_tab[c].defined; + } + break; + case OP_FLG: + { + int flag_num; + + if (cti_int_num(&flag_num)) error("Za FLG musˇ bt ‡ˇslo!"); + if (flag_num>255) error("€ˇslo vlajky (FLG) musˇ bt v rozsahu 0-255!"); + hodn=(test_flag(flag_num)!=0); + } + break; + default: + { + char c[200]; + sprintf(c,"%s%s.TMP",pathtable[SR_TEMP],text); + hodn=!access(c,0); + } + break; + } + hodn^=not_op;not_op=0; + if (last_op) vysl&=hodn;else vysl|=hodn; + ODD=cti_oddelovac(); + } + return vysl; + } + +static char proved_prikaz() + { + char prikaz[20]; + char text[128]; + int c; + char op; + + ODD=cti_oddelovac(); + while (ODD==OD_NEWLINE) ODD=cti_oddelovac(); //preskoc prazdne radky + if (ODD==OD_IN) return 0; //cti znak { + do + { + while (ODD==OD_NEWLINE || ODD==OD_COMMAND) ODD=cti_oddelovac(); + if (ODD!=0) error("O‡ek v  se jm‚no definice (p©ˇklad: INDX=)"); + cti_retezec(20,prikaz,1,1); + op=get_symbol(prikaz); + if (op==OP_BREAK) return 1; + ODD=cti_oddelovac(); + if (ODD!=OD_SET) ex_error(OD_SET); + switch(op) + { + case OP_INDX: + if (cti_int_num(&c)) error("INDX=?"); + if (c<0 || c>255) error("INDX=<0,255>"); + index_tab[last_index=c].defined=1; + break; + case OP_TEXT: + cti_retezec(128,text,0,0); + index_tab[last_index].text=NewArr(char,strlen(text)+1); + strcpy(index_tab[last_index].text,text); + break; + case OP_MAP: + cti_retezec(13,index_tab[last_index].mapname,1,1); + break; + case OP_DRAW: + { + char file[20]; + int xp,yp; + int h; + + cti_retezec(20,file,1,1); + ODD=cti_oddelovac();if (ODD!=OD_COMMA)ex_error(OD_COMMA); + if (cti_int_num(&xp)) error("O‡ek v  se ‡ˇslo xp"); + ODD=cti_oddelovac();if (ODD!=OD_COMMA)ex_error(OD_COMMA); + if (cti_int_num(&yp)) error("O‡ek v  se ‡ˇslo yp"); + h=find_handle(file,pcx_8bit_decomp); + if (h==-1) def_handle(h=end_ptr++,file,pcx_8bit_decomp,SR_DIALOGS); + put_picture(xp,yp+SCREEN_OFFLINE,ablock(h)); + } + break; + case OP_UNDEF: + if (cti_int_num(&c)) error("UNDEF=?"); + if (c<0 || c>255) error("UNDEF=<0,255>"); + index_tab[c].defined=0; + break; + case OP_USEMAP: + { + char file[20]; + cti_retezec(20,file,1,1); + usemap=find_handle(file,pcx_8bit_nopal); + if (usemap==-1) def_handle(usemap=end_ptr++,file,pcx_8bit_nopal,SR_DIALOGS); + } + break; + case OP_ESCAPE: + { + char *s; + cti_retezec(20,prikaz,1,1); + fclose(glbm); + s=find_map_path(prikaz); + if ((glbm=fopen(s,"r"))==NULL) error(s); + free(s); + return 0; + } + default:error(prikaz); + } + ODD=cti_oddelovac(); + if (ODD!=OD_COMMAND && ODD!=OD_NEWLINE && ODD!=EOF) ex_error(OD_COMMAND); + } + while (ODD!=OD_NEWLINE && ODD!=EOF); + return 0; + } + +static void preskoc_prikaz(void) + { + char ending=0; + int uroven=0; + char last; + char text; + + do + { + last=ODD; + ODD=cti_oddelovac(); + switch (ODD) + { + case 0:cti_retezec(1,&text,0,0);ending=1;break; + case '\n':if (ending && uroven==0) return;break; + case EOF: if (uroven!=0)ex_error(OD_OUT);return;break; + case '{': if (last==OD_CRIT || last==OD_NEWLINE) uroven++;break; + case '}': if (last==OD_NEWLINE) uroven--; if (uroven<0) ex_error(OD_IN); + else if (uroven==0)return;break; + } + if (ODD!=0) ending=0; + } + while(1); + } + +static void do_script(void) + { + char *s; + char vysledek; + + s=find_map_path(GLOBMAP); + linecounter=0; + glbm=fopen(s,"r"); + free(s); + if (glbm==NULL) error("Chybˇ uveden soubor..."); + ODD=cti_oddelovac(); + do + { + if (ODD==0) //existuji kriteria + { + vysledek=test_kriterii(); + } + else vysledek=1; + if (ODD==OD_CRIT) //oddelovac kriterii + { + char c=0; + if (vysledek)c=proved_prikaz();else preskoc_prikaz(); + if (c) break; + } + ODD=cti_oddelovac(); + } + while(ODD!=EOF); + fclose(glbm); + } + +static int found_place=0; + + +static char flp_validate2(word sector) + { + TMOB *m; + char c; + + if (mob_map[sector]) + { + m=mobs+mob_map[sector]-1; + if (m->vlajky & ~MOB_PASSABLE) return 0; + if (!m->next) + if (mobs[m->next-1].vlajky & ~MOB_PASSABLE) return 0; + } + c=map_sectors[sector].sector_type; + if (c==S_DIRA || ISTELEPORT(c) || c==S_LAVA || c==S_VODA ) return 0; + return 1; + } + +static char flp_validate(word sector) + { + TMOB *m; + char c; + + if (found_place) return 0; + if (mob_map[sector]) + { + m=mobs+mob_map[sector]-1; + if (m->vlajky & ~MOB_PASSABLE) return 0; + if (!m->next) + if (mobs[m->next-1].vlajky & ~MOB_PASSABLE) return 0; + } + c=map_sectors[sector].sector_type; + if (~map_coord[sector].flags & 1) return 0; + if (c==S_DIRA || ISTELEPORT(c) || c==S_LAVA || c==S_VODA ) return 0; + if (c==S_LEAVE && !found_place) found_place=sector; + return 1; + } + + +static int find_leave_place(int sector) + { + found_place=0; + if (map_sectors[sector].sector_type==S_LEAVE) return sector; + labyrinth_find_path(sector,65535,(SD_PLAY_IMPS | SD_SECRET),flp_validate,NULL); + return found_place; + } + +macro_load_another_map(); + +static select_mode; + + +static char load_index_map(int index) + { + TMA_LOADLEV x; + int lv,i; + THUMAN *h; + + + if (select_mode) + { + char *a; + + a=alloca(strlen(index_tab[index].mapname)+1);strcpy(a,index_tab[index].mapname); + wire_automap_file(a); + return 1; + } + if (!strcmp(index_tab[last_index].mapname,level_fname)) return 0; + lv=find_leave_place(viewsector); + if (lv<1) + { + bott_disp_text(texty[121]); + return 0; + } + for(i=0,h=postavy;iused && h->lives) + if (h->sektor!=lv && !labyrinth_find_path(h->sektor,lv,(SD_PLAY_IMPS | SD_SECRET),flp_validate2,NULL)) + { + char c[20]; + bott_disp_text(itoa(i,c,10)); + return 0; + } + if (!GlobEvent(MAGLOB_LEAVEMAP,viewsector,viewdir)) return 0; + for(i=0,h=postavy;iused && h->lives) h->sektor=lv; + viewsector=lv; + strncpy(x.name,index_tab[index].mapname,12); + x.start_pos=0; + x.dir=0; + macro_load_another_map(&x); + return 0; + } + +static char *fly_text; +static int fly_x,fly_y,fly_xs,fly_ys; +static void *fly_background; + +EVENT_PROC(global_map_point) + { + MS_EVENT *ms; + + user_ptr; + WHEN_MSG(E_INIT) + { + fly_background=NULL;last_index=0;fly_text=NULL; + fly_x=0;fly_y=0;fly_xs=4;fly_ys=4; + } + WHEN_MSG(E_MOUSE) + { + int x,y,i,xs,ys; + char *ptr; + ms=get_mouse(msg); + if (ms->event_type & 0x1) + { + x=ms->x;y=ms->y-SCREEN_OFFLINE; + if (y<0 || y>359) return; + else + { + alock(usemap); + ptr=ablock(usemap); + ptr+=640*y+x+6; + i=*ptr; + } + y+=60; + schovej_mysku(); + if (fly_background!=NULL)put_picture(fly_x,fly_y,fly_background); + set_font(H_FTINY,RGB555(31,31,0)); + xs=fly_xs;ys=fly_ys; + if (i!=last_index) + { + free(fly_background); + last_index=i; + if (index_tab[i].defined) + { + fly_text=index_tab[i].text; + mouse_set_default(H_MS_ZARE); + set_ms_finger(5,5); + } + else + { + fly_text=NULL; + mouse_set_default(H_MS_DEFAULT); + } + + if (fly_text!=NULL) + { + xs=text_width(fly_text)+4; + ys=text_height(fly_text)+4; + fly_background=NewArr(word,xs*ys*2+6); + } + else + { + fly_text=NULL;xs=4;ys=4; + fly_background=NULL; + } + } + if (fly_text!=NULL) + { + if ((x+xs)>639) x=639-xs; + get_picture(x,y,xs,ys,fly_background); + trans_bar(x,y,xs,ys,0); + position(x+2,y+2);outtext(fly_text); + } + send_message(E_MOUSE,msg); + ukaz_mysku(); + showview(fly_x,fly_y,fly_xs+1,fly_ys); + showview(fly_x=x,fly_y=y,(fly_xs=xs)+1,fly_ys=ys); + aunlock(usemap); + } + if (ms->event_type & 0x2 && ms->y>SCREEN_OFFLINE && ms->y<378) + { + if (last_index && index_tab[last_index].defined) if (load_index_map(last_index)) return; + else;else return; + unwire_proc(); + wire_proc(); + msg->msg=-1; + } + if (ms->event_type & 0x8) + { + unwire_proc(); + wire_proc(); + msg->msg=-1; + } + } + WHEN_MSG(E_DONE) + { + free(fly_background); + } + } + +void unwire_global_map() + { + purge_index_tab(); + send_message(E_DONE,E_MOUSE,global_map_point); + set_select_mode(0); + pick_set_cursor(); + } + + +void wire_global_map() + { + unwire_proc(); + schovej_mysku(); + ready_index_tab(); + do_script(); + ukaz_mysku(); + showview(0,0,0,0); + send_message(E_ADD,E_MOUSE,global_map_point); + unwire_proc=unwire_global_map; + change_click_map(NULL,0); + } + +static void *old_wire_save; +static int old_viewsector; +static void empty_unwire() + { + + } + +static void unwire_automap_file() + { + load_map_automap(level_fname); + wire_proc=old_wire_save; + viewsector=old_viewsector; + build_player_map(); + bott_draw(0); + wire_proc(); + } + +void wire_automap_file(char *mapfile) + { + int c; + if ((c=get_leaving_place(mapfile))==0) return; + old_wire_save=wire_proc; + old_viewsector=viewsector; + viewsector=c; + unwire_proc(); + unwire_proc=empty_unwire; + wire_proc=unwire_automap_file; + save_map_state(); + load_map_automap(mapfile); + noarrows=1; + cur_mode=MD_ANOTHER_MAP; + show_automap(1); + cancel_render=1; + } + +char set_select_mode(char mode) + { + char last=select_mode; + select_mode=mode; + return last; + } + +void cestovat() + { + + } + + diff --git a/GAME/INTERFAC.C b/GAME/INTERFAC.C new file mode 100644 index 0000000..402a7a9 --- /dev/null +++ b/GAME/INTERFAC.C @@ -0,0 +1,1623 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#include "engine1.h" + +#define MES_MAXSIZE 500 +#define CHECK_BOX_ANIM 6 + +static char *error_hack="....Source compiled."; +static char shadow_enabled=1; + +word color_topbar[7]={0,RGB555(22,14,4),RGB555(24,16,6),RGB555(25,17,7)}; + +int input_txtr=H_LOADTXTR; + +void create_frame(int x,int y,int xs,int ys,char clear) + { + word *line; + word *col; + int i; + + x-=VEL_RAMEC; + y-=VEL_RAMEC; + xs=(xs+VEL_RAMEC-1)/VEL_RAMEC+1; + ys=(ys+VEL_RAMEC-1)/VEL_RAMEC+1; + line=GetScreenAdr()+y*scr_linelen2+x; + col=line; + put_8bit_clipped(ablock(H_RAMECEK),col,0,VEL_RAMEC,VEL_RAMEC);col+=VEL_RAMEC; + for(i=1;ilight,border3d->shadow); + + for(i=border3d->bsize-1;i>=0;i--) + if (border3d->ctldef & (1<x,w->y,w->xs-10,w->ys-10,w->color,&w->border3d); + if (shadow_enabled) + { + trans_bar((w->x+10),w->y+w->ys-10,(w->xs-10),10,0); + trans_bar(w->x+w->xs-10,w->y+10,10,w->ys-20,0); + } + else shadow_enabled=1; + } + +void add_window(int x,int y,int xs,int ys,int texture,int border,int txtx,int txty) + { + CTL3D wb; + WINDOW *p; + + xs&=~1; + wb.bsize=abs(border); + wb.ctldef=-1*(border<0); + wb.light=txtx; + wb.shadow=txty; + p=create_window(x,y,xs,ys,texture,&wb); + p->draw_event=show_textured_win; + desktop_add_window(p); + + } + + +void zalamovani(char *source,char *target,int maxxs,int *xs,int *ys) + { + strcpy(target,source); + xs[0]=0; + ys[0]=0; + if ((xs[0]=text_width(target))>maxxs) + { + char c[2]=" "; + char *ls,*ps,*cs; + int sum; + + cs=ps=target; + do + { + ls=NULL; + sum=0; + while (summaxws) maxws=z1; + if (z2>wsys) wsys=z2; + } + maxws+=10; + if (maxws<50) maxws=50; + wscelk=(pocet_textu-1)*(maxws+20); + if (wscelk>maxxs) maxxs=wscelk; + wsy=10+wsys; + maxys+=wsy+40; + if (maxys<50) maxys=50; + maxxs+=20; + add_window(x1=320-(maxxs>>1),y1=180-(maxys>>1),x2=maxxs+10,y2=maxys+10,H_WINTXTR,2,0,0); + message_win[0].xlu=x1; message_win[0].ylu=y1; message_win[0].xrb=x1+x2;message_win[0].yrb=y1+y2; + change_click_map(message_win,2); + set_window_modal(); + y=10; + while (text[0]) + { + define(-1,10,y,1,1,0,label,text); + y+=text_height(text); + text=strchr(text,0)+1; + } + wsx=(maxxs-wscelk)>>1; + for(i=1;iid; + send_message(E_DONE,E_KEYBOARD,message_keyboard,keys); + close_current(); + restore_click_map(clksav,clksav2); + return id; + } + +//------------------ + +void type_text(EVENT_MSG *msg,void **data) + { + static int x,y; + static char text[255],index; + static char *source; + static int max_size,max_chars; + + data; + if (msg->msg==E_INIT) + { + int *p; + char *c; + + set_font(H_FBOLD,RGB555(31,31,31)); + p=msg->data; + x=p[0]; + y=p[1]; + c=*(char **)(p+2); + max_size=*(int *)(p+3); + max_chars=*(int *)(p+4); + strcpy(text,c); + source=c; + index=strchr(text,0)-text; + strcat(text,"_"); + schovej_mysku(); + put_textured_bar(ablock(input_txtr),x,y,max_size,text_height(text),0,0); + position(x,y);outtext(text); + ukaz_mysku(); + showview(x,y,max_size,20); + } + else + if (msg->msg==E_MOUSE) + { + MS_EVENT *ms; + + ms=get_mouse(msg); + if (ms->event_type & 0x8) send_message(E_KEYBOARD,27); + if (ms->event_type & 0x2) send_message(E_KEYBOARD,13); + } + else if (msg->msg==E_KEYBOARD) + { + char c; + + c=*(char *)msg->data; + set_font(H_FBOLD,RGB555(31,31,31)); + if (c) + { + switch (c) + { + case 8:if (index) index--; text[index]='_';text[index+1]=0;break; + case 13:text[index]=0;strcpy(source,text); + case 27:send_message(E_DONE,E_MOUSE,type_text); + send_message(E_DONE,E_KEYBOARD,type_text); + return; + default:if (c>=32) + { + text[index]=c;index++; + text[index]='_'; + text[index+1]=0; + if (text_width(text)>max_size || strlen(text)>(unsigned)max_chars) text[--index]=0; + } + } + schovej_mysku(); + put_textured_bar(ablock(input_txtr),x,y,max_size,text_height(text),0,0); + position(x,y);outtext(text); + ukaz_mysku(); + showview(x,y,max_size,20); + } + msg->msg=-1; + } + } + +#define COL_SIZE 776 + +typedef void (*type_text_exit_proc)(char); + +void type_text_v2(va_list args) +//rutina je pro vstup radky, po ukonceni zavola proceduru exit_proc pokud uzivatel stiskne ENTER +//volat jako task +//#pragma aux type_text_v2 parm [] + { + char *text_buffer=va_arg(args,char *); + int x=va_arg(args,int); + int y=va_arg(args,int); + int max_size=va_arg(args,int); + int max_chars=va_arg(args,int); + int font=va_arg(args,int); + int color=va_arg(args,int); + type_text_exit_proc exit_proc=va_arg(args,type_text_exit_proc); + + int xs,ys,tw; + char *text,pos,len; + char wait_loop=1,ok=0,edit=0; + short *back_pic; + int i; + + task_sleep(NULL); + schovej_mysku(); + set_font(font,color); + xs=max_size+text_width("_"); + if (max_chars<257) text=alloca(257); else text=alloca(max_chars); + for(i=0;i<255;i++) text[i]=i+1; + text[i]=0;ys=text_height(text)+5; + strcpy(text,text_buffer); + back_pic=getmem(xs*ys*2+6); + get_picture(x,y,xs,ys,back_pic); + pos=strlen(text); + len=pos; + tw=text_width(text); + do + { + char sz[2]=" "; + word znak,px; + + put_picture(x,y,back_pic); + position(x,y); + set_font(font,color); + outtext(text); + sz[0]=text[pos];text[pos]=0; + px=text_width(text);text[pos]=sz[0]; + position(px+x,y+3);outtext("_"); + ukaz_mysku(); + showview(x,y,xs,ys); + znak=*(word *)task_wait_event(E_KEYBOARD); //proces bude cekat na klavesu + schovej_mysku(); + if (task_quitmsg()==1) znak=27; + switch(znak & 0xff) + { + case 8:if (pos>0) + { + pos--; + strcpy(&text[pos],&text[pos+1]); + len--; + } + break; + case 13:strcpy(text_buffer,text); + ok=1; + case 27:wait_loop=0; + break; + case 0:switch(znak>>8) + { + case 'K': if (pos>0) pos--;break; + case 'M': if (pospos) + { + strcpy(text+pos,text+pos+1); + len--; + } + break; + case 't':while (pos0) + { + pos--; + if (text[pos]==' ') break; + } + break; + } + break; + default:sz[0]=znak & 0xff; + if (edit) + { + if (sz[0]<32 || tw+text_width(sz)>max_size || len>=max_chars) break; + memmove(&text[pos+1],&text[pos],len-pos+1); + text[pos]=sz[0]; + len++; + pos++; + } + else + { + text[0]=sz[0]; + text[1]=0; + len=1; + pos=1; + } + break; + } + tw=text_width(text); + edit=1; + } + while (wait_loop); + put_picture(x,y,back_pic); + position(x,y); + set_font(font,color); + outtext(text); + ukaz_mysku(); + showview(x,y,xs,ys); + free(back_pic); + exit_proc(ok); + } + + +void col_load(void **data,long *size) + { + int siz=*size; + char *s,*c; + int palcount; + int i;//,j,k; + + palcount=siz/COL_SIZE; + *size=PIC_FADE_PAL_SIZE*palcount; + s=getmem(*size); + c=*data;c+=8; + for(i=0;i>16) +#define Lo(x) ((x)& 0xffff) + + +char labyrinth_find_path(word start,word konec,int flag,char (*proc)(word),word **cesta) + { + longint *stack; + longint *stk_free; + longint *stk_cur; + char *ok_flags; + char vysl; + + if (cesta!=NULL) *cesta=NULL; + stk_free=stk_cur=stack=getmem(4*(mapsize+2)); + memset(ok_flags=getmem((mapsize+8)/8),0,(mapsize+8)/8); + ok_flags[start>>3]|=1<<(start & 0x7); + for(*stk_free++=start;stk_free!=stk_cur;stk_cur++) + { + char i;word s,d,ss; + s=(ss=Lo(*stk_cur))<<2; + for(i=0;i<4;i++) if (!(map_sides[s+i].flags & flag)) + { + char c; + word w; + d=map_sectors[ss].step_next[i]; + c=1<<(d & 0x7); + w=d>>3; + if (!(ok_flags[w] & c) && proc(d)) + { + ok_flags[w]|=c; + *stk_free++=d | ((stk_cur-stack)<<16); + } + if (d==konec) break; + } + if (d==konec) break; + } + vysl=0; + if (stk_free!=stk_cur) + { + if (cesta!=NULL) + { + int count=0; + longint *p,*z; + word *x; + + z=p=stk_free-1; + while (Lo(*p)!=start) + { + int l; + count++; + l=*p; + p=Hi(l)+stack; + *z--=Lo(l); + } + x=*cesta=getmem(count*2+2); + z++; + while (count--) + { + *x++=(word)*z++; + } + *x++=0; + } + vysl=1; + } + free(stack); + free(ok_flags); + return vysl; + } + +typedef struct radio_butt_data + { + void *picture; + char *texty; + }TRADIO_BUTT_DATA; + +static void radio_butts_init(OBJREC *o,long *params) + { + char *c,*z; + long cnt=0,*q,*d,*zz; + int i; + TRADIO_BUTT_DATA *rd; + + d=params; + for (i=0;i<*params;i++) + { + d+=1; + c=get_title(d); + cnt+=strlen(c);cnt++; + } + rd=New(TRADIO_BUTT_DATA); + o->userptr=(void *)rd; + zz=q=(long *)getmem(cnt+8); + *q++=1;*q++=*params; + d=params; + z=(char *)q; + for (i=0;i<*params;i++) + { + d+=1; + c=get_title(d); + strcpy(z,c); + z=strchr(z,'\0');z++; + } + rd->picture=NULL; + rd->texty=(char *)zz; + } + +static void radio_butts_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + int step,size,sizpul,i; + long *params; + char *texts; + CTL3D *clt; + TRADIO_BUTT_DATA *rd; + + x2; + rd=(TRADIO_BUTT_DATA *)o->userptr; + params=(long *)rd->texty; + step=(y2-y1)/(*(params+1)); + size=(step*9)/10; + sizpul=size>>1; + if (rd->picture==NULL) + { + rd->picture=NewArr(short,3+(size)*(y2-y1)); + get_picture(x1,y1,size,y2-y1,rd->picture); + } + else + put_picture(x1,y1,rd->picture); + + texts=(char *)(params+2); + clt=def_border(5,curcolor); + for (i=0;i<*(params+1);i++,y1+=step) + { + if (*(long *)o->data==i) + { + int xx1=x1+2,yy1=y1+1,xx2=x1+size-2,yy2=y1+size-3,xxs=(xx1+xx2)>>1,yys=(yy1+yy2)>>1; + curcolor=0x0; + line(xx2+1,yy1+2,xxs+2,yy2+2); + line(xx1+1,yys+2,xxs+1,yy2+2); + curcolor=RGB555(31,31,31); + line(xx2,yy1+1,xxs+1,yy2+1); + line(xx1,yys+1,xxs,yy2+1); + line(xx2,yy1,xxs+1,yy2); + line(xx1,yys,xxs,yy2); + } + draw_border(x1+1,y1+1,size-2,size-2,clt); + if (*params) + { + set_aligned_position(x1+size+5,y1+sizpul,0,1,texts); + outtext(texts); + texts=strchr(texts,'\0')+1; + } + } + } + +static void radio_butts_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + int sel; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x02) + { + TRADIO_BUTT_DATA *rd; + long *params; + + rd=(TRADIO_BUTT_DATA *)o->userptr; + params=(long *)rd->texty; + sel=(ms->y-o->locy)/(o->ys/(*(params+1))); + if (sel>=*(params+1)) sel=*(params+1)-1; + *(long *)o->data=sel; + *params=0; + redraw_object(o); + *params=1; + set_change(); + } + } + + } + +static void radio_butts_done(OBJREC *o) + { + TRADIO_BUTT_DATA *rd; + + rd=(TRADIO_BUTT_DATA *)o->userptr; + free(rd->picture); + free(rd->texty); + }; + +void radio_butts_gr(OBJREC *o) + { + o->runs[0]=radio_butts_init; + o->runs[1]=radio_butts_draw; + o->runs[2]=radio_butts_event;; + o->runs[3]=radio_butts_done;; + o->datasize=4; + } + +char ask_test(char *text,char def) + { + char znak; + SEND_LOG("(START CHECK) %s",text,0); + cprintf("\n\r%s (A/N, Cokoliv=%c)\x7",text,def); + znak=getche(); + if (znak>='a' && znak<='z') znak-='a'-'A'; + if (znak!='N' && znak!='A') znak=def; + return znak=='A'; + } + +long get_disk_free(char disk) + { + return 10*1024*1024; +/* struct diskfree_t ds; + if (_dos_getdiskfree(disk,&ds)==0) + return ds.avail_clusters*ds.sectors_per_cluster*ds.bytes_per_sector; + return 0;*/ + } + +void start_check() + { + /* + char *c; + unsigned drv; + long siz; + struct meminfo memory; + get_mem_info(&memory); + concat(c,pathtable[SR_TEMP],TEMP_FILE); +// if (!access(c,F_OK)) +// if (ask_test("Skeldal nebyl spr vn ukon‡en. Ml bys provest kontrolu disku\n\rMam spustit SCANDISK?",'A')) +// system("SCANDISK /NOSUMMARY"); + if (pathtable[SR_TEMP][1]==':') drv=pathtable[SR_TEMP][0];else + { + _dos_getdrive(&drv);drv+='@'; + } + if (drv>='a' && drv<='z') drv-='a'-'A'; + siz=get_disk_free(drv-'@')/1024; + SEND_LOG("Checking system enviroment - Largest Free Block %u bytes/pages %d",memory.LargestBlockAvail,memory.NumPhysicalPagesFree); + SEND_LOG("Checking system enviroment - Disk space on %c: %d Kb",drv,siz); + c=alloca(1024); + if (siz<1024) + { + sprintf(c,"Na disku %c: nenˇ pot©ebn‚ 1 MB pro ukl d nˇ pozic. Hrozˇ ‘e pozice nebude kam ukl dat\n\rP©esto spustit?",drv); + if (!ask_test(c,'N')) exit(1); + } + else if (siz<50000 && level_preload==1 && memory.LargestBlockAvail<50000000) + { + sprintf(c,"Na disku %c: neni nutnch 50 MB pro odkl d nˇ dat. Skeldal bude ¨et©it\n\r" + "s pamtˇ a nahr vat jen pot©ebn  data. Hra se m–‘e rapidn zpomalit!\n\r" + "Mam to udlat?",drv); + if (ask_test(c,'A')) level_preload=0; + } + */ + } +/* +typedef struct dos_extra_block + { + long sector; + word pocet; + word buffer_ofs; + word buffer_seg; + }; + + +typedef struct disk_label + { + word nula; + long serial; + char label[11]; + char type[8]; + }; +*/ +/*static void read_1st_sector(char drive,char *sector) + { + word segment; + word selector; + word exseg; + word exbuf; + void *ptr; + struct dos_extra_block *data; + + RMREGS regs; + + dosalloc(32,&segment,&selector); + dosalloc(2,&exseg,&exbuf); + ptr=(void *)(segment<<4); + data=(void *)(exseg<<4); + data->sector=0; + data->pocet=1; + data->buffer_ofs=0; + data->buffer_seg=segment; + regs.eax=drive; + regs.ecx=0xffff; + regs.ds=exseg; + regs.ebx=0; + rmint(0x25,0,0,®s); + memcpy(sector,ptr,512); + dosfree(selector); + dosfree(exbuf); + } + + */ +/* +long read_serial(char drive) + { + word segment; + word selector; + struct disk_label *p; + RMREGS regs; + long serial; + + dosalloc(32,&segment,&selector); + regs.eax=0x6900; + regs.ebx=drive; + regs.ds=segment; + regs.edx=0; + rmint(0x21,0,0,®s); + p=(void *)(segment<<4); + serial=p->serial; + dosfree(selector); + return serial; + } + +static void crash_event1(THE_TIMER *t) + { + long serial; + int i; + + serial=read_serial(t->userdata[1]); + serial=~serial; + if (serial==t->userdata[0]) return; + outp(0x64,0xfe); + send_message(E_PRGERROR,&i); + exit(0); + } + +static void crash_event2(THE_TIMER *t) + { + long serial; + int i; + + serial=read_serial(t->userdata[1]); + serial=~serial; + if (serial==t->userdata[0]) return; + outp(0x64,0xfe); + send_message(E_PRGERROR,&i); + exit(0); + } + +static void crash_event3(THE_TIMER *t) + { + long serial; + int i; + + serial=read_serial(t->userdata[1]); + serial=~serial; + if (serial==t->userdata[0]) return; + outp(0x64,0xfe); + send_message(E_PRGERROR,&i); + exit(0); + } + + +#pragma aux check_number_1phase parm[]; +void check_number_1phase(char *exename) //check serial number! + { + THE_TIMER *t; + int h; + char buffer[_MAX_PATH]; + unsigned short date,time; + long serial; + + _fullpath(buffer,exename,_MAX_PATH); + t=add_to_timer(TM_HACKER,2000,1,crash_event1); + t->userdata[0]=*(long *)error_hack; + t->userdata[1]=(long)buffer[0]-'@'; + t=add_to_timer(TM_HACKER,3000,1,crash_event2); + t->userdata[0]=*(long *)error_hack; + t->userdata[1]=(long)buffer[0]-'@'; + h=open(exename,O_RDONLY); + _dos_getftime(h,&date,&time); + serial=(date<<16) | time; + t=add_to_timer(TM_HACKER,4000,1,crash_event3); + t->userdata[0]=~serial; + t->userdata[1]=(long)buffer[0]-'@'; + close(h); + } + +*/ +static void skeldal_checkbox_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + word *obr; + char *data; + int phase; + + y2,x2; + data=(char *)o->data; + obr=ablock(H_CHECKBOX); + if (o->userptr==NULL) + { + o->userptr=NewArr(word,obr[0]*obr[0]+3); + obr=ablock(H_CHECKBOX); + get_picture(x1,y1,obr[0],obr[0],o->userptr); + } + else + put_picture(x1,y1,o->userptr); + phase=(CHECK_BOX_ANIM-(*data>>1))*20; + put_8bit_clipped(obr,GetScreenAdr()+x1+y1*scr_linelen2,phase,obr[0],obr[0]); + } + +static void skeldal_checkbox_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x2) + { + char *data=(char *)o->data; + + *data^=1; + set_change(); + } + } + } + +void animate_checkbox(int first_id,int last_id,int step) + { + int i; + + for(i=first_id;i<=last_id;i+=step) + { + char c; + char pos; + + c=f_get_value(0,i); + pos=c>>1; + if (c & 1 && pos0) + { + c-=2; + c_set_value(0,i,c); + } + } + } + +void skeldal_checkbox(OBJREC *o) + { +// o->runs[0]=skeldal_checkbox_init; + o->runs[1]=skeldal_checkbox_draw; + o->runs[2]=skeldal_checkbox_event; + o->datasize=1; + } + +//------------------------------------------ + +static void setup_button_init(OBJREC *o,char **params) + { + void **d; + d=NewArr(void *,2); + d[0]=NewArr(char,strlen(*params)+1); + strcpy(d[0],*params); + d[1]=NULL; + o->userptr=(void *)d; + *(char *)o->data=0; + } + +static void setup_button_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + char *s; + char data; + void **z; + word *pic; + word *bb; + int x,y; + + z=(void **)o->userptr; + s=z[0]; + bb=ablock(H_SETUPOK); + pic=z[1];if (pic==NULL) + { + pic=NewArr(word,bb[0]*bb[1]+3); + bb=ablock(H_SETUPOK); + get_picture(x1,y1,bb[0],bb[1],pic); + } + data=*(char *)o->data; + if (data) put_picture(x1,y1,bb); else if (z[1]!=NULL) put_picture(x1,y1,pic); + x=(x1+10+x2)>>1;y=(y1+y2)>>1; + set_aligned_position(x,y,1,1,s); + outtext(s); + z[1]=pic; + } + +static void setup_button_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x2) + { + *(char *)o->data=1;redraw_object(o); + } + else if (ms->event_type & 0x4) + { + *(char *)o->data=0;redraw_object(o);set_change(); + } + } + else if (msg->msg==E_LOST_FOCUS) + { + *(char *)o->data=0;redraw_object(o); + } + } + +static void setup_button_done(OBJREC *o) + { + void **z; + + z=o->userptr; + free(z[0]); + free(z[1]); + free(z); + o->userptr=NULL; + } + +void setup_ok_button(OBJREC *o) + { + o->runs[0]=setup_button_init; + o->runs[1]=setup_button_draw; + o->runs[2]=setup_button_event; + o->runs[3]=setup_button_done; + o->datasize=1; + } + +//----------------------------------------------------- + +static void skeldal_soupak_init (OBJREC *o,int *params) + { + void **d; + d=NewArr(void *,2); + d[0]=(void *)*params; + d[1]=NULL; + o->userptr=d; + } + +static void skeldal_soupak_draw (int x1,int y1,int x2,int y2,OBJREC *o) + { + void **z; + int rozsah; + int value; + word *pic; + word *back; + int total; + int xpos; + + z=o->userptr; + rozsah=(int)z[0]; + pic=ablock(H_SOUPAK); + total=y2-y1-pic[1]; + value=*(int *)o->data; + xpos=y2-pic[1]-value*total/rozsah; + back=z[1]; + if (back==NULL) + { + back=NewArr(word,(x2-x1+1)*(y2-y1+1)+3); + get_picture(x1,y1,(x2-x1+1),(y2-y1+1),back); + z[1]=back; + pic=ablock(H_SOUPAK); + } + else + put_picture(x1,y1,back); + put_picture(x1,xpos,pic); + } + +static skeldal_soupak_event(EVENT_MSG *msg,OBJREC *o) + { + if (msg->msg==E_MOUSE) + { + MS_EVENT *ms; + int *z; + int rozsah; + int total; + word *pic; + int ypos,newvalue; + + ms=get_mouse(msg); + if (ms->tl1) + { + z=o->userptr;rozsah=z[0]; + pic=ablock(H_SOUPAK); + total=o->ys-pic[1]; + ypos=ms->y-o->locy; + ypos+=pic[1]/2; + newvalue=(o->ys-ypos)*rozsah/total; + if (newvalue<0) newvalue=0; + if (newvalue>rozsah) newvalue=rozsah; + *(int *)o->data=newvalue; + redraw_object(o); + set_change(); + } + } + } + +static void skeldal_soupak_done(OBJREC *o) + { + void **z; + + z=o->userptr; + free(z[1]); + free(z); + o->userptr=NULL; + } + + + +void skeldal_soupak(OBJREC *o) + { + o->runs[0]=skeldal_soupak_init; + o->runs[1]=skeldal_soupak_draw; + o->runs[2]=skeldal_soupak_event; + o->runs[3]=skeldal_soupak_done; + o->datasize=4; + } + + +static char fletna_str[13]; +static char pos=0; + +// C C# D D# E F F# G G# A A# B C +// A B C D E F G H I J K L M +static char smery[4][13]= + { + "CHLJLH", //DGBABG + "BDEDGE", //C#D#ED#F#E + "LHJGHE", + "CIGILI" + }; + +void fletna_pridej_notu(char note) + { + note+=65; + fletna_str[pos]=note; + if (pos==13) memcpy(fletna_str,fletna_str+1,pos); + else pos++; + } + +static void play_wav(int wav,int sector) + { + if (check_snd_effect(SND_GFX)) + { + play_sample_at_sector(wav,sector,sector,0,0); + } +/* else + { + struct t_wave *p; + char *sample; + int siz; + + p=ablock(wav); + sample=(char *)p+sizeof(struct t_wave); + memcpy(&siz,sample,4);sample+=4; + pc_speak_play_sample(sample,siz,(p->freq!=p->bps?2:1),p->freq); + }*/ + } + +static play_random_sound(int sector,int dir,int pos) + { + int seed; + int v; + + seed=rand(); + srand(sector+dir); + while (pos--) + do + { + v=rnd(8); + } + while (v==dir); + play_wav(H_SND_SEVER+v,sector); + srand(seed); + } + +static play_correct_sound(int sector,int dir) + { + play_wav(H_SND_SEVER+dir,sector); + } + +void check_fletna(THE_TIMER *t) + { + char len; + char *s; + int sec; + int dir; + + t; + if (!pos) return; + sec=t->userdata[0]; + dir=t->userdata[1]; + s=smery[dir]; + len=strlen(s); + if (len==pos) + { + if (!strncmp(s,fletna_str,pos) && map_sectors[sec].sector_type==dir+S_FLT_SMER) + play_correct_sound(sec,dir); + else + play_random_sound(sec,dir,pos); + } + else + play_random_sound(sec,dir,pos); + pos=0; + } + +char fletna_get_buffer_pos() + { + return pos; + } + +static char globFletnaStr[256]=""; +static char globNotes[][3]={"C","C#","D","D#","E","F","F#","G","G#","A","A#","H","C"}; + +void fletna_glob_add_note(char note) +{ + if (strlen(globFletnaStr)<250) strcat(globFletnaStr,globNotes[note]); +} + +static char compareMelody(const char *m1,const char *m2) +{ + while (*m1 && *m2) + { + if (!isalpha(*m1) && *m1!='#') m1++; + else if (!isalpha(*m2) && *m2!='#') m2++; + else if (toupper(*m1)!=toupper(*m2)) break; + else + { + m1++; + m2++; + } + + } + if (*m1>*m2) return 1; + if (*m1<*m2) return -1; + return 0; +} + +void check_global_fletna(THE_TIMER *t) + { + int sec; + int dir; + int i; + int other=-1; + + t; + sec=t->userdata[0]; + dir=t->userdata[1]; + if (globFletnaStr[0] && globFletnaStr[strlen(globFletnaStr)-1]==32) + { + globFletnaStr[strlen(globFletnaStr)-1]=0; + } + for (i=MAGLOB_ONFLUTE1;i<=MAGLOB_ONFLUTE8 ;i++) + if (GlobEventList[i].param!=0) + { + { + const char *cmp=level_texts[GlobEventList[i].param]; + if (compareMelody(cmp,globFletnaStr)==0) + { + GlobEvent(i,sec,dir); + globFletnaStr[0]=0; + return; + } + } + } + else if (GlobEventList[i].sector || GlobEventList[i].side) other=i; + if (other!=-1) + GlobEvent(other,sec,dir); + globFletnaStr[0]=0; + } + + +//--------------------------------------- + +char *find_map_path(char *filename) + { + char *p1,*p; + + if (pathtable[SR_MAP2]!=NULL) + { + concat(p1,pathtable[SR_MAP2],filename); + if (!access(p1,0)) goto found; + } + concat(p1,pathtable[SR_MAP],filename); + found: + p=NewArr(char,strlen(p1)+1); + strcpy(p,p1); + return p; + } + +FILE *enc_open(char *filename,ENCFILE *fil) + { + FILE *f,*g; + char *c,*d,*enc,*temp; + int i,j,last=0; + + f=fopen(filename,"r"); + if (f!=NULL) + { + fil->f=f; + fil->to_delete=NULL; + return f; + } + enc=alloca(strlen(filename)+5); + strcpy(enc,filename); + c=strrchr(enc,'.'); + if (c==NULL) c=strchr(enc,0); + strcpy(c,".ENC"); + f=fopen(enc,"rb"); + if (f==NULL) + { + fil->f=NULL; + fil->to_delete=NULL; + return NULL; + } + d=strrchr(enc,'\\');if(d==NULL)d=enc;else d++; + temp=malloc((i=strlen(pathtable[SR_TEMP]))+strlen(d)+1); + strcpy(temp,pathtable[SR_TEMP]); + strcat(temp,d); + d=temp+i; + d=strrchr(d,'.'); + strcpy(d,".dec"); + g=fopen(temp,"wb"); + if (g==NULL) + { + free(temp); + fclose(f); + fil->f=NULL; + fil->to_delete=NULL; + return NULL; + } + i=getc(f); + while (i!=EOF) + { + j=(last+i) & 0xff; + last=j; + putc(j,g); + i=getc(f); + } + fclose(f); + fclose(g); + f=fopen(temp,"r"); + if (f==NULL) + { + free(temp); + fil->f=NULL; + fil->to_delete=NULL; + return NULL; + } + fil->f=f; + fil->to_delete=temp; + return f; + } + +void enc_close(ENCFILE *fil) + { + fclose(fil->f); + if (fil->to_delete!=NULL) remove(fil->to_delete); + free(fil->to_delete); + fil->f=NULL; + fil->to_delete=NULL; + } + + +int load_string_list_ex(TSTR_LIST *list,char *filename) + { + char c[1024],*p; + int i,j,lin=0; + FILE *f; + ENCFILE fl; + + f=enc_open(filename,&fl); + if (*list==NULL) *list=create_list(256); + if (f==NULL) return -1; + do + { + lin++; + do + { + j=fgetc(f); + if (j==';') while ((j=fgetc(f))!='\n' && j!=EOF); + if (j=='\n') lin++; + } + while (j=='\n'); + ungetc(j,f); + j=fscanf(f,"%d",&i); + if (j==EOF) + { + enc_close(&fl); + return -2; + } + if (j!=1) + { + enc_close(&fl); + return lin; + } + if (i==-1) break; + while ((j=fgetc(f))<33 && j!=EOF); + if (j!=EOF) ungetc(j,f); + if (fgets(c,1022,f)==NULL) + { + enc_close(&fl); + return lin; + } + p=strchr(c,'\n');if (p!=NULL) *p=0; + for(p=c;*p;p++) *p=*p=='|'?'\n':*p; + if (str_replace(list,i,c)==NULL) + { + enc_close(&fl); + return -3; + } + } + while (1); + enc_close(&fl); + return 0; + } + +//------------------------------------------------------------ +int smlouvat_nakup(int cena,int ponuka,int posledni,int puvod,int pocet) + { + int min=cena-((cena-puvod)*2*(pocet-1)/(pocet+1)); + int d_ok=posledni=cena) return 0; + if (ponuka<=posledni || ponukar_ok) return 0; + if (p_ok>75) return 2; + if (p_ok>50) return 3; + if (p_ok>25) return 4; + return 5; + } + +int smlouvat_prodej(int cena,int ponuka,int posledni,int puvod,int pocet) + { + int min=cena+((puvod-cena)*2/pocet); + int d_ok=posledni==0?min-cena:(min+posledni)/2-cena; + int p_ok=(min-ponuka)*100/(d_ok+1); + int r_ok=rnd(100); + + if (ponuka==0) return 0; + if (ponuka<=cena) return 0; + if (posledni!=0) if (ponuka>=posledni || ponuka>min) return 1; + if (p_ok>r_ok) return 0; + if (p_ok>75) return 2; + if (p_ok>50) return 3; + if (p_ok>25) return 4; + return 5; + } + +static smlouvat_enter(EVENT_MSG *msg,OBJREC *o) + { + o; + if (msg->msg==E_KEYBOARD) + { + switch( *(char *)msg->data) + { + case 13:goto_control(30);terminate();break; + case 27:goto_control(20);terminate();break; + } + } + } + +int smlouvat(int cena,int puvod,int pocet,int money,char mode) + { + int ponuka=0,posledni=0; + char text[255],*c,buffer[20]; + int y,yu,xu; + int temp1,temp2; + + cena,puvod,pocet,money;text[0]=0;text[1]=0; + add_window(170,130,300,150,H_IDESKA,3,20,20); + define(-1,10,15,1,1,0,label,texty[241]); + set_font(H_FBOLD,RGB555(31,31,31));define(-1,150,15,100,13,0,label,itoa(cena,buffer,10)); + set_font(H_FBOLD,MSG_COLOR1); + define(-1,10,30,1,1,0,label,texty[238]); + define(10,150,30,100,13,0,input_line,8);property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default(""); + on_event(smlouvat_enter); + define(20,20,20,80,20,2,button,texty[239]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_change(terminate); + define(30,110,20,80,20,2,button,texty[230]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_change(terminate); + do + { + redraw_window(); + schovej_mysku();set_font(H_FBOLD,RGB555(31,31,31)); + c=text;yu=y=waktual->y+50;xu=waktual->x+10; + do {position(xu,y);outtext(c);y+=text_height(c)+1;c=strchr(c,0)+1;} while(*c); + ukaz_mysku(); + showview(xu,yu,280,y-yu); + goto_control(10); + escape(); + temp1=1; + if (o_aktual->id==20) cena=-1; + else + { + get_value(0,10,buffer); + if (buffer[0]==0) c=texty[240]; + else + { + if (sscanf(buffer,"%d",&ponuka)!=1) c=texty[237]; + else + { + if (ponuka>money && mode==1) c=texty[104]; + else + { + if (mode) temp1=smlouvat_nakup(cena,ponuka,posledni,puvod,pocet); + else temp1=smlouvat_prodej(cena,ponuka,posledni,puvod,pocet+1); + posledni=ponuka; + if (rnd(100)<50) c=texty[230+temp1];else c=texty[250+temp1]; + } + } + } + shadow_enabled=0; + } + if (c) zalamovani(c,text,280,&temp2,&temp2); + } + while (temp1!=0 && cena!=-1); + if (temp1==0) cena=ponuka; + close_current(); + shadow_enabled=1; + return cena; + } + +//----------------- JRC LOGO ---------------------------------- + +#define SHOWDELAY 125 +#define SHOWDEND (SHOWDELAY-32) + +typedef struct _hicolpal + { + unsigned blue:5; + unsigned green:5; + unsigned red:5; + }HICOLPAL; + +void show_jrc_logo(char *filename) + { + char *s; + char *pcx;word *pcxw; + char bnk=1; + int xp,yp,i; + word palette[256],*palw; + int cntr,cdiff,cpalf,ccc; + + change_music("?"); + curcolor=0;bar(0,0,639,479); + showview(0,0,0,0);Sleep(1000); + concat(s,pathtable[SR_VIDEO],filename); + if (open_pcx(s,A_8BIT,&pcx)) return; + pcxw=(word *)pcx; + xp=pcxw[0]; + yp=pcxw[1]; + palw=pcxw+3; + memcpy(palette,palw,256*sizeof(word)); + memset(palw,0,256*sizeof(word)); + xp/=2;yp/=2;xp=320-xp;yp=240-yp; + cntr=get_timer_value();ccc=0; + do + { + cdiff=(get_timer_value()-cntr)/2; + if (cdiffr) palw[i]=r;else palw[i]=k; + k=palette[i] & 0x7e0;if (k>g) palw[i]|=g;else palw[i]|=k; + k=palette[i] & 0x1f;if (k>b) palw[i]|=b;else palw[i]|=k; + } + } + else if (ccc!=cdiff) + { + cpalf=SHOWDELAY-cdiff; + if (cpalf<32) + for (i=0;i<256;i++) + { + int r,g,b,k=32-cpalf; + + b=palette[i];g=b>>5;b&=0x1f;r=g>>6;g&=0x1f; + b-=k;r-=k;g-=k; + if (b<0) b=0; + if (r<0) r=0; + if (g<0) g=0; + palw[i]=b | (r<<11) | (g<<6); + } + } + if (!bnk) wait_retrace();put_picture(xp,yp,pcx); + if (bnk) {wait_retrace();showview(xp,yp,pcxw[0],pcxw[1]);} + ccc=cdiff; + mix_back_sound(0); + } + while (cdiff +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include + +#define neprezbrojit() (battle && (battle_mode!=MD_PREZBROJIT || select_player!=human_selected-postavy)) + +#define _SHOP_ST "_SHOPS.TMP" + +#define SV_ITLIST 0x8001 +#define SV_SNDLIST 0x8002 +#define SV_END 0x8000 +#define IT_LIBS 27 +#define IT_LIB_NAME "IKONY%02d.LIB" +#define IT_LIB_SIZE 18 +#define SHOP_NAME "SHOPS.DAT" + + +#define BUYBOX_X 0 +#define BUYBOX_Y 197 + +#define IMAP_SIZE 8 + +#define SHP_ICSIZX 54 +#define SHP_ICSIZY 60 +#define SHP_ICPLCX 30 +#define SHP_ICPLCY 29 + + +THUMAN postavy_2[20]; +int face_arr[IT_FACES]; +static int sound_handle; +int ikon_libs; +int item_count,it_count_orgn; +LETICI_VEC *letici_veci=NULL; + +short *picked_item=NULL; +short water_breath=-1; //vec pro dychani pod vodou +short flute_item=-1; +int item_in_cursor=0; + +void (*inv_redraw)(); + +TSHOP *cur_shop; +TSHOP **shop_list=NULL;int max_shops=0; //shop_list=prima spojeni s obchody +void *shop_hacek=NULL; //hacek za ktery visi cely shop strom (free(shop_hacek) - odalokuje shopy) + //hacek lze ulozit do savegame -> ulozi se cely stav obchodu +long shop_hacek_size=0; //toto je jeho delka + +#define ico_extract(icnnum) (((char*)ablock(ikon_libs+(icnnum)/IT_LIB_SIZE))+IT_ICONE_SIZE*((icnnum)%IT_LIB_SIZE)) + +#define TOP_OFS 17 +#define HUMAN_X 35 +#define HUMAN_Y 348 +#define INV_X 285 +#define INV_Y (TOP_OFS+29) +#define INV_DESC_X 325 +#define INV_DESC_Y (TOP_OFS+50) +#define INV_XS 55 +#define INV_YS 60 +#define INV_NAME_X 129 +#define INV_NAME_Y 349 +#define INV_NAME_COL (RGB555(10,31,31)) +#define INV_DESK 266 +#define INV_INFO_X 298 +#define INV_INFO_Y 343 +#define INV_INFO_XS 300 +#define INV_INFO_YS 20 +#define INV_INFO_XP 12 +#define INV_INFO_YC (INV_INFO_YS+INV_INFO_XP) +#define INV_BRIEF_COL1 (NOSHADOW(0)) +#define INV_BRIEF_COL2 (NOSHADOW(0)) +#define INV_LEVEL_COL1 (NOSHADOW(RGB555(0,0,15))) +#define INV_LEVEL_COL2 (RGB555(31,24,0)) + +unsigned short butt_plus[]={0x0,(RGB555(25,23,16)),(RGB555(18,17,14)),(RGB555(10,10,5)),(RGB555(31,27,14))}; + +#define PO_XS 194 +#define PO_YS 340 +#define PO_XSS (PO_XS>>1) +#define PO_YSS (PO_YS>>1) + +TITEM *glob_items=NULL; +char inv_view_mode=0; + +void redraw_inventory(); +void zkontroluj_postavu(); + +void place_human_item(word *obrazek,int x,int y,int item) + { + word *p; + + p=ablock(item); + put_picture2picture(p,obrazek,PO_XSS-p[0]/2+x,PO_YS-p[1]-y-20); + } + +/* +void init_item_sounds(int *ptr) + { + int i; + char *c; + + for(i=0;i=*s) return; + pal=((word *)(cur+pos))+3; + for (j=0;j<256;j++,pal++) + { + *pal=RGB555(*pal>>10,(*pal>>5)& 0x1F,(*pal & 0x1F)); + } + } + } + +void load_items() + { + char *name; + FILE *f;THANDLE_DATA *h; + int sect,i,hs; + long size; + void *p; + + f=NULL;i=0; + ikon_libs=hl_ptr; + free(glob_items); + do + { + char name[200]; + sprintf(name,IT_LIB_NAME,i++); + if (test_file_exist(SR_ITEMS,name)) + h=def_handle(hl_ptr++,name,items_15to16_correct,SR_ITEMS); + else break; + } + while (1); + name=find_map_path(ITEM_FILE); + f=fopen(name,"rb");free(name); + if (f==NULL) + { + closemode(); + MessageBox(NULL,"Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje.",NULL,MB_OK|MB_ICONSTOP); + exit(0); + } + do + { + load_section(f,&p,§,&size); + switch (sect) + { + case 1: + case 4: + face_arr[sect-1]=hl_ptr-1; + prepare_graphics(&hl_ptr,(char *)p,size,pcx_fade_decomp,SR_ITEMS); + free(p); + break; + case 2: + case 3: + face_arr[sect-1]=hl_ptr-1; + prepare_graphics(&hl_ptr,(char *)p,size,pcx_fade_decomp,SR_ITEMS); + free(p); + break; + case 5: + face_arr[sect-1]=hl_ptr-1; + prepare_graphics(&hl_ptr,(char *)p,size,NULL,SR_ITEMS); + free(p); + break; + case SV_ITLIST: + glob_items=p; + it_count_orgn=item_count=size/sizeof(TITEM); + break; + case SV_SNDLIST: + hs=hl_ptr; + prepare_graphics(&hl_ptr,(char *)p,size,wav_load,SR_ZVUKY); + sound_handle=hs-1; + break; + default: + free(p); + break; + } + } + while (sect!=SV_END); + fclose(f); + { + TITEM *t; + for(i=0,t=glob_items;idruh==TYP_SPECIALNI) + { + if (t->user_value==TSP_WATER_BREATH) water_breath=i; + else if (t->user_value==TSP_FLUTE) flute_item=i; + } + } + + } + +void init_items() + { + map_items=(short **)getmem(mapsize*4*sizeof(short **)); + memset(map_items,0,mapsize*4*sizeof(short **)); + } + +static short expand_itemlist(void) + { + int nwit=item_count; + + if (item_count>32766) + { + int i,j; + + for(i=it_count_orgn;i32766) + { + nwit=32766; + memmove(glob_items+it_count_orgn,glob_items+it_count_orgn,(item_count-it_count_orgn-1)*sizeof(TITEM)); + item_count=32766; + memcpy(&it[nwit],&glob_items[item],sizeof(TITEM)); + } + else + { + it=(TITEM *)getmem(sizeof(TITEM)*item_count); + memcpy(it,glob_items,sizeof(TITEM)*nwit); + memcpy(&it[nwit],&glob_items[item],sizeof(TITEM)); + free(glob_items); + } + it[nwit].flags|=ITF_DUPLIC; + glob_items=it; + return nwit+1; + }*/ + +short duplic_item(short item) + { + int i; + + if (!item) return item; + item--; + for(i=0;i0) + { + sect=*(int *)c; + c+=sizeof(sect)/sizeof(short);s-=sizeof(sect); + d=c;itmc=1; + while (*d++) itmc++; + map_items[sect]=(short *)getmem(itmc*sizeof(short)); + d=c; + itmc=0; + do + { + map_items[sect][itmc++]=*d; + s-=sizeof(short); + } + while (*d++); + c=d; + } + } + +char possx[]={0,1,1,0}; +char possy[]={1,1,0,0}; + +void draw_placed_items_normal(int celx,int cely,int sect,int side) + { + int i,j,k; + short *c; + short nl=0,vzh; + short cnt; + + + sect<<=2; + cnt=(cely==0)?2:4; + for(i=0;i0) + { + vzh=glob_items[(*c)-1].vzhled; + if (vzh) draw_item(celx,cely,possx[i],possy[i],ablock(vzh+face_arr[0]),k); + } + c++;k++; + } + } + } + +int count_items_total(short *place) + { + int c=0; + + if (place==NULL) return 0; + while (*place++) c++; + return c; + } + +int count_items_visible(short *place) + { + int c=0; + + if (place==NULL) return 0; + while (*place) + { + if (*place>0) c++; + place++; + } + return c; + } + + +int count_items_inside(short *place) + { + int c=1; + + if (place==NULL) return 0; + place++; + while (*place++<0) c++; + return c; + } + +int find_item(short *place,int mask) + { + int lastitem=-1; + int i=0; + + if (place==NULL) return -1; + while (*place) + { + if ((*place & 0xC000)==mask) lastitem=i; + i++;place++; + } + return lastitem; + } + +static int lastsector; + +static char ValidateSector(word sector) + { + int pp=map_sectors[sector].sector_type; + if (pp==S_NORMAL || pp==S_SMER || pp==S_LEAVE || pp==S_FLT_SMER) + { + lastsector=sector; + return 1; + } + return 0; + } + +void push_item(int sect,int pos,short *picked_item) + { + int bc; + int pc; + int tc; + short *p; + + if (map_sectors[sect].sector_type==S_DIRA || ISTELEPORTSECT(sect)) + sect=map_sectors[sect].sector_tag; + if (sect==0 || map_sectors[sect].sector_type==S_VODA) + { + if (game_extras & EX_RECOVER_DESTROYED_ITEMS) + { + labyrinth_find_path(viewsector,65535,SD_PLAY_IMPS,ValidateSector,NULL); + push_item(lastsector,viewdir,picked_item); + return; + } + else + { + free(picked_item); + picked_item=NULL; + return; + } + } + sect=(sect<<2)+pos; + bc=count_items_total(map_items[sect]); + pc=count_items_total(picked_item); + tc=bc+pc; + if (tc==0) return; + tc++; + p=(short *)grealloc(map_items[sect],tc*sizeof(short)); + if (pc) memcpy(p+bc,picked_item,pc*sizeof(short)); + p[tc-1]=0; + map_items[sect]=p; + recheck_button(sect>>2,1); + } + +void pop_item(int sect,int pos,int mask,short **picked_item) + { + int picked; + int bc,tc,pc; + short *s,*t,*b; + + *picked_item=NULL; + sect=(sect<<2)+pos; + picked=find_item(map_items[sect],mask); + if (picked==-1) return; + s=map_items[sect]+picked; + pc=count_items_inside(s); + bc=count_items_total(map_items[sect]); + tc=bc-pc; + *picked_item=(short *)getmem((pc+1)*sizeof(short)); + memcpy(*picked_item,s,pc*sizeof(short));(*picked_item)[pc]=0; + if (tc) b=NewArr(short,tc+1);else b=NULL; + if (picked) memcpy(b,map_items[sect],picked*sizeof(short)); + t=b+picked; + s=s+pc; + while (*s) *t++=*s++; + if (b!=NULL) b[tc]=0; + free(map_items[sect]); + map_items[sect]=b; + recheck_button(sect>>2,1); + } + +void pick_set_cursor(void) + { + if (picked_item==NULL) + item_in_cursor=H_MS_DEFAULT; + else + item_in_cursor=-(glob_items[*picked_item-1].ikona); + mouse_set_default(item_in_cursor); + } + + + + +void do_items_specs(void) + { + int xa,ya; + char destroy=0; + TITEM *p; + GlobEvent(MAGLOB_ONPICKITEM,viewsector,viewdir); + if (picked_item==0) return; + + p=&glob_items[*picked_item-1]; + switch(p->druh) + { + case TYP_RUNA:xa=p->user_value/10;ya=1<<(p->user_value%10); + runes[xa]|=ya; + destroy=1; + play_fx_at(FX_MAGIC); + if (game_extras & EX_AUTOSHOWRUNE) bott_disp_rune(p->user_value,*picked_item-1); + break; + case TYP_PENIZE: + { + //char c[150]; + money+=p->cena; + destroy=1; + //sprintf(c,texty[cislovka(p->cena)+131],p->cena); + //bott_disp_text(c); + play_fx_at(FX_MONEY); + break; + } + case TYP_PRACH: + destroy=1; + bott_disp_text(texty[134]); + break; + case TYP_SVITXT: + destroy=1; + cur_page=count_pages(); + cur_page&=~0x1; + cur_page++; + if (p->popis[0]==0) add_to_book(p->user_value); + else + { + char *s; + s=find_map_path(p->popis); + add_text_to_book(s,p->user_value); + free(s); + } + play_fx_at(FX_BOOK); + if (game_extras & EX_AUTOOPENBOOK) autoopenaction=1; + break; + } + if (destroy) + { + destroy_items(picked_item); + free(picked_item); + picked_item=NULL; + } + } + +static char check_pick(int sect,int id,int idd,int y) + { + short c; + int min=480,d; + short *place=map_items[(sect<<2)+idd]; + int vzl; + + if (place==NULL) return 0; + while (*place) + { + c=*place; + if (c>0) + { + vzl=glob_items[c-1].vzhled; + if (vzl) d=get_item_top(0,id>1,possx[id],possy[id],ablock(vzl+face_arr[0]),count_items_visible(place)-1); + else d=get_item_top(0,id>1,possx[id],possy[id],NULL,count_items_visible(place))-32; + if (dmin; + } + +static get_top_of_next(int sect,int id) //vraci souradnici predmetu na nasledujicim sektoru + { + int cnt,idd; + + sect=map_sectors[sect].step_next[viewdir]; + if (sect==0) return 0; + id=3-id; + idd=id+viewdir & 3;sect<<=2; + cnt=count_items_visible(map_items[sect+idd])-1; + if (cnt<0) cnt=0; + return get_item_top(0,1,possx[id],possy[id],NULL,cnt); + + } + +char pick_item_(int id,int xa,int ya,int xr,int yr) + { + int sect; + int idd; + + xa,ya,xr,yr; + if (id>1) + { + (sect=map_sectors[viewsector].step_next[viewdir]); + if ((map_sides[(viewsector<<2)+viewdir].flags & SD_THING_IMPS) && !(map_sides[(viewsector<<2)+viewdir].oblouk & SD_ITPUSH)) return 0; + } + else sect=viewsector; + idd=(id+viewdir)&0x3; + if (picked_item!=NULL) + { + if (map_sectors[sect].sector_type==S_DIRA) + { + throw_fly(xa,ya,0); + letici_veci->speed=0; + letici_veci->sector=sect; + letici_veci->xpos=-32; + letici_veci->velocity=0; + letici_veci->flags &= ~FLY_NEHMOTNA; + } + else + if (id>1 || ya>=get_top_of_next(sect,id)) + { + if ((game_extras & EX_BAG_EXTENDED) && (GetKeyState(VK_CONTROL) & 0x80) && + (glob_items[*picked_item-1].nosnost>0)) + { + int curinside=count_items_inside(picked_item); + int nosnost=(glob_items[*picked_item-1].nosnost); + short *batoh=(word *)getmem(nosnost*2+20); + short *cur=batoh; + memcpy(cur,picked_item,(curinside+1)*2); + cur+=curinside; + free(picked_item); + picked_item=NULL; + nosnost-=curinside-1; + while (1) + { + pop_item(sect,idd,0,&picked_item); + if (picked_item!=NULL) do_items_specs(); else break; + if (picked_item!=NULL) + { + short *p=picked_item; + int cnt=count_items_total(picked_item); + if (cnt>nosnost) + { + push_item(sect,idd,picked_item); + free(picked_item); + picked_item=NULL; + break; + } + while (*p) + { + *cur++=-abs(*p++); + nosnost--; + } + free(picked_item); + picked_item=NULL; + } + } + *cur=0; + picked_item=batoh; + pick_set_cursor(); + return 1; + } + push_item(sect,idd,picked_item); + free(picked_item); + picked_item=NULL; + pick_set_cursor(); + return 1; + } + return 0; + } + else + { + if (id>1 || check_pick(sect,id,idd,ya)) + { + pop_item(sect,idd,0,&picked_item); + if (picked_item!=NULL) do_items_specs(); + pick_set_cursor(); + } + return (picked_item!=NULL); + } + } + +int celkova_vaha(short *p) + { + int suma=0; + + while (*p) suma+=glob_items[abs(*p++)-1].hmotnost; + return suma; + } + +char put_item_to_inv(THUMAN *p,short *picked_items) + { + int i,pos=0; + int it; + + if (p->inv_size>MAX_INV) p->inv_size=MAX_INV; + if (picked_items==NULL) return 0; + if (isdemon(p)) return 0; + it=*picked_items; + if (it && glob_items[it-1].umisteni==PL_SIP && !neprezbrojit()) + { + int u; + u=glob_items[it-1].user_value;if (!u) u=1; + if (p->sipy+u<100) + { + p->sipy+=u; + return 1; + } + } + for(i=0;picked_items[i];i++); + while (i) + { + for(;posinv_size && p->inv[pos];pos++); + if (pos>=p->inv_size) break; + i--; + it=abs(picked_items[i]); + p->inv[pos]=it; + picked_items[i]=0; + } + return (i==0); + } + +//-----------------------------------Inventory viewer------------------- + +THUMAN *human_selected=postavy; +short vls_min[24]= + {0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0}; +short vls_max[]= + {200,200,200,200,32767,32767,32767,190,199,190,199,99,99,99,99,99,90,90,90,90,99,4}; + +char bag_click(int id,int xa,int ya,int xr,int yr); +char human_click(int id,int xa,int ya,int xr,int yr); +char inv_swap_desk(int id,int xa,int ya,int xr,int yr); +char exit_inv(int id,int xa,int ya,int xr,int yr); +char ring_place(int id,int xa,int ya,int xr,int yr); +char uloz_sip(int id,int xa,int ya,int xr,int yr); + +char info_box_drawed=0; +void *info_box_below=NULL; +void *inv_keyboard(EVENT_MSG *msg,void **usr); + +T_CLK_MAP clk_inv_view[]= + { + {-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,bag_click,2,-1}, + {0,236,185,255,204,ring_place,2,-1}, + {1,236,220,255,239,ring_place,2,-1}, + {2,236,255,255,274,ring_place,2,-1}, + {3,236,290,255,309,ring_place,2,-1}, + {0,0,200,29,309,uloz_sip,2,-1}, + {-1,37,34,225,336,human_click,2,-1}, + {-1,45,339,212,358,inv_swap_desk,2,H_MS_DEFAULT}, + {-1,54,378,497,479,start_invetory,2+8,-1}, + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {-1,0,0,639,479,exit_inv,8,-1}, + }; + +#define CLK_INV_VIEW 13 + +void prepocitat_postavu(THUMAN *human_selected) + { + short *sr1,*p,*q,i,j,c; + int v; + + if (human_selected->inv_size>MAX_INV) human_selected->inv_size=MAX_INV; + sr1=human_selected->vlastnosti; + p=human_selected->stare_vls; + memcpy(sr1,p,sizeof(human_selected->stare_vls)); + for(i=0;iwearing[i];else c=human_selected->prsteny[i-HUMAN_PLACES]; + if (c) + { + p=sr1; + q=glob_items[c-1].zmeny; + for(j=0;j=VLS_OHEN && j<=VLS_MYSL) + p[0]=(int)floor(((float)p[0]+(float)q[0])/(1.0f+(float)p[0]*(float)q[0]/(90.0*90.0))+0.5); + else + (*p)+=(*q); + } + p++,q++; + } + p=sr1+VLS_DAMAGE; //vypocet damage (bez omezeni) + q=&glob_items[c-1].zmeny[VLS_DAMAGE]; + *(p++)+=*q++; + p=sr1+VLS_KOUZLA; //aplikace kouzel + q=&glob_items[c-1].zmeny[VLS_KOUZLA]; + (*p++)|=*q++; + } + } + p=sr1; + for(j=0;jvls_max[j]) *p=vls_max[j]; + p++; + } + if (human_selected->lives>human_selected->vlastnosti[VLS_MAXHIT]) human_selected->lives=human_selected->vlastnosti[VLS_MAXHIT]; + //if (human_selected->mana>human_selected->vlastnosti[VLS_MAXMANA]) human_selected->mana=human_selected->vlastnosti[VLS_MAXMANA]; + if (human_selected->kondice>human_selected->vlastnosti[VLS_KONDIC]) human_selected->kondice=human_selected->vlastnosti[VLS_KONDIC]; + v=MAX_HLAD(human_selected);human_selected->jidlo=min(human_selected->jidlo,v); + v=MAX_ZIZEN(human_selected);human_selected->voda=min(human_selected->voda,v); + } + + +char exit_inv(int id,int xa,int ya,int xr,int yr) + { + inv_view_mode=0; + if (!battle || battle_mode!=MD_PREZBROJIT || picked_item==NULL) return_game(id,xa,ya,xr,yr); + return 1; + } + + +void definuj_postavy() + { + int i,num1,r,inv=0,z; + char *c,*end,cc; + + c=ablock(H_POSTAVY_DAT); + end=c+get_handle(H_POSTAVY_DAT)->size; + for(i=0;cinv_size=6; + while (cjmeno);r--;break; + case 129:r=sscanf(c,"%hd",&p->female);break; + case 130:r=sscanf(c,"%hd",&p->xicht);break; + case 131:r=sscanf(c,"%hd",&p->level);break; + case 132:r=sscanf(c,"%d",&p->exp);break; + case 133:r=sscanf(c,"%d",&num1); + while(r==1 && num1!=-1) + { + p->inv[inv++]=num1+1; + c=strchr(c,'\n')+1; + r=sscanf(c,"%d",&num1); + } + break; + case 134:r=sscanf(c,"%hd",&p->wearing[PO_BATOH]); + p->inv_size=6+glob_items[p->wearing[PO_BATOH]].nosnost; + p->wearing[PO_BATOH]++; + break; + case 135:r=sscanf(c,"%d",&num1);if (r!=1) break; + c=strchr(c,'\n')+1; + r=sscanf(c,"%hd",&p->wearing[num1]); + p->wearing[num1]++; + break; + case 136:r=sscanf(c,"%d",&num1);if (r!=1) break; + p->sipy=num1; + break; + default:r=sscanf(c,"%hd",&p->stare_vls[num1]);break; + } + if (c>=end) break; + c=strchr(c,'\n')+1; + } + if (r!=1) + { + closemode(); + MessageBox(NULL,"Error in file POSTAVY.DAT. May be missing a parameter in some definition.",NULL,MB_OK|MB_ICONSTOP); + exit(0); + } + c=strchr(c,'\n')+1; + prepocitat_postavu(p); + p->lives=p->vlastnosti[VLS_MAXHIT]; + p->kondice=p->vlastnosti[VLS_KONDIC]; + p->mana=p->vlastnosti[VLS_MAXMANA]; + p->used=1; + p->groupnum=1; + p->jidlo=MAX_HLAD(p); + p->voda=MAX_ZIZEN(p); + p->bonus=0; + p->mana_battery=32767; + } + } + +static void inv_najist(short item) + { + TITEM *it; + int mhlad; + + if (!item) return; + it=glob_items+item-1; + if (it->druh!=TYP_JIDLO) return; + human_selected->jidlo+=it->user_value*HODINA; + mhlad=MAX_HLAD(human_selected); + play_sample_at_channel(H_SND_EAT,1,100); + if (human_selected->jidlo>mhlad) human_selected->jidlo=mhlad; + if (it->magie>0) + thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1); + bott_draw(1); + redraw_inventory(); + } + +static void inv_napit(short item) + { + TITEM *it; + int mvoda; + + if (!item) return; + it=glob_items+item-1; + if (it->druh!=TYP_VODA) return; + human_selected->voda+=it->user_value*HODINA; + mvoda=MAX_ZIZEN(human_selected); + play_sample_at_channel(H_SND_LEKTVAR,1,100); + if (human_selected->voda>mvoda) human_selected->voda=mvoda; + if (it->magie>0) + thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1); + bott_draw(1); + redraw_inventory(); + } + +static void inv_quaf(short item) + { + TITEM *it; + + if (!item) return; + it=glob_items+item-1; + if (it->druh!=TYP_LEKTVAR) return; + thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1); + bott_draw(1); + play_sample_at_channel(H_SND_LEKTVAR,1,100); + redraw_inventory(); + } + +static void inv_use_spec(short **items) + { + short *pp; + short it; + + pp=*items; + if (pp==NULL) return; + it=*pp; + if (!it) return; + it--; + if (it==flute_item) + { + unwire_proc(); + wire_proc(); + bott_draw_fletna(); + if (put_item_to_inv(human_selected,pp)) + { + free(pp); + *items=NULL; + } + poloz_vsechny_predmety(); + pick_set_cursor(); + } + } + +char check_jidlo_voda(THUMAN *p) + { + if (game_extras & EX_NOHUNGRY) return 0; + if (p->used && p->lives) + { + p->jidlo--; + p->voda--; + if (p->jidlo<0) + { + p->jidlo=0; + return 1; + } + if (p->voda<0) + { + p->voda=0; + player_hit(p,1,0); + return 1; + } + } + return 0; + } + +char check_map_specials(THUMAN *p) + { + char c=0; + switch(mglob.map_effector) + { + case ME_NORMAL:break; + case ME_SOPKA:if (~p->vlastnosti[VLS_KOUZLA] & SPL_FIRE_RES) player_hit(p,10,0),c=1;break; + case ME_LEDOV:if (~p->vlastnosti[VLS_KOUZLA] & SPL_ICE_RES) player_hit(p,10,0),c=1;break; + } + if (c) bott_draw(0); + return c; + } + +void pomala_regenerace_postavy(THUMAN *p) + { + int mreg,mmax; + check_map_specials(p); + if (check_jidlo_voda(p)) return; + if (p->utek) + { + p->utek=0; + if (p->kondice>0) p->kondice-=1; + return; + } + p->kondice+=(p->vlastnosti[VLS_VPREG]+9)/10; + if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC]; + mreg=(p->vlastnosti[VLS_MPREG]+9)/10; + mmax=p->vlastnosti[VLS_MAXMANA]; + if (p->mana+mreg>mmax) mreg=mmax-p->mana; + if (mreg>0) p->mana+=mreg; + } + + +char sleep_regenerace(THUMAN *p) + { + int mreg,mmax; + if (p->used && p->lives) + { + if (check_jidlo_voda(p)) return 1; + p->kondice+=p->vlastnosti[VLS_VPREG]; + p->lives+=p->vlastnosti[VLS_HPREG]; + if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC]; + if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; + mreg=p->vlastnosti[VLS_MPREG]; + mmax=p->vlastnosti[VLS_MAXMANA]; + if (p->mana+mreg>mmax) mreg=mmax-p->mana; + if (mreg>0) p->mana+=mreg; + } + return 0; + } + + +void real_regeneration() + { + int i; + THUMAN *p; + + for(i=0;iused && p->lives) + pomala_regenerace_postavy(p); + } + send_message(E_KOUZLO_KOLO); + sleep_ticks+=MAX_SLEEP/30; + if (sleep_ticks>MAX_SLEEP) sleep_ticks=MAX_SLEEP; + tick_tack(1); + TimerEvents(viewsector,viewdir,game_time); + SEND_LOG("(GAME) Tick Tack, Game time: %d",game_time,0); + GlobEvent(MAGLOB_ONROUND,viewsector,viewdir); + bott_draw(0); + } + +void init_inventory(void) + { + definuj_postavy(); + } + +void display_items_in_inv(THUMAN *h) + { + int i,x,y,xr,yr,it; + short *p; + + put_picture(266,TOP_OFS,ablock(H_IDESKA)); + p=ablock(H_IMRIZ1); + p[1]=INV_YS*((h->inv_size-1)/6)+58; + put_picture(INV_X,INV_Y,p); + xr=INV_X;x=0; + yr=INV_Y;y=0; + for(i=0;iinv_size;i++) + { + if ((it=h->inv[i])!=0) + { + int ikn; + + ikn=glob_items[it-1].ikona; + put_picture(xr,yr,ico_extract(ikn)); + } + xr+=INV_XS; + x++;if (x>=6) + { + xr=INV_X;yr+=INV_YS;x=0; + } + } + } + +void display_rings() + { + word pozice[][2]= + { + {245,194},{245,229},{245,264},{245,299} + }; + int i; + + for(i=0;i<4;i++) + { + int ikn; + + ikn=human_selected->prsteny[i]; + if (ikn) + { + word *w; + ikn=glob_items[ikn-1].ikona; + w=(word *)ico_extract(ikn); + put_picture(pozice[i][0]-w[0]/2,pozice[i][1]-w[1]/2,w); + } + } + } + +void *build_items_wearing(THUMAN *h) + { + int i,vzhled,it; + word *p,hx,hy; + word *ob; + size_t siz; + char *pp; + + p=ablock(H_CHARS+h-postavy); + hx=p[0]; + hy=p[1]; + ob=getmem(siz=(PO_XS*PO_YS+PIC_FADE_PAL_SIZE)); + memset(ob,0,siz); + memcpy(ob,p,PIC_FADE_PAL_SIZE); + ob[0]=PO_XS; + ob[1]=PO_YS; + put_picture2picture(p,ob,PO_XSS-(hx/2),PO_YS-hy-20); + for(i=1;iwearing[i])!=0) + { + TITEM *itt; + + itt=&glob_items[it-1]; + vzhled=itt->vzhled; + if (h->female==1) vzhled+=face_arr[2];else vzhled+=face_arr[1]; + if (i==PO_RUKA_L) place_human_item(ob,itt->polohy[1][0],itt->polohy[1][1],vzhled); + else place_human_item(ob,itt->polohy[0][0],itt->polohy[0][1],vzhled); + } + pp=(char *)ob; + if (h->vlastnosti[VLS_KOUZLA] & SPL_STONED) + { + int i; + for (i=0;i<(PIC_FADE_PAL_SIZE>>1);++i) if (i>3) + { + unsigned short col=ob[i]; + int bw=(GET_R_COLOR(col)+GET_G_COLOR(col)+GET_B_COLOR(col))/3; + if (bw>255) bw=255; + ob[i]=RGB(bw,bw,bw); + } + } + else + { + pp+=PIC_FADE_PAL_SIZE; + if (h->vlastnosti[VLS_KOUZLA] & SPL_INVIS) + for(i=0;iwearing[PO_BATOH]; + if (it) + { + TITEM *itt; + word *w;int vzhled; + + itt=&glob_items[it-1]; + vzhled=itt->vzhled; + if (h->female==1) vzhled+=face_arr[2];else vzhled+=face_arr[1]; + w=ablock(vzhled); + enemy_draw(w,GetScreenAdr()+itt->polohy[0][0]+HUMAN_X+PO_XSS-w[0]/2+scr_linelen2*(HUMAN_Y-itt->polohy[0][1]-20),6,320,HUMAN_Y,640*65536); + } + } + + +void write_human_big_name(char *c) + { + int xs,ys; + + set_font(H_FBOLD,INV_NAME_COL); + xs=text_width(c)>>1; + ys=text_height(c)>>1; + position(INV_NAME_X-xs,INV_NAME_Y-ys); + outtext(c); + } + + + +#define pvls(x) (offsetof(struct thuman,vlastnosti[x])) +#define ptpw(x) (offsetof(struct thuman,bonus_zbrani[x])) +static void percent_bar(int x,int y,int xs,int ys,int val,int max,char *popis) + { + CTL3D clt; + char s[25]; + + memcpy(&clt,def_border(3,0),sizeof(clt)); + bar(x,y,x+xs*val/max,ys+y); + show_textured_button(x-2,y-2,xs+5,ys+5,0,&clt); + set_aligned_position(x,y-5,0,2,popis); + outtext(popis); + sprintf(s,"%d/%d",val/360,max/360); + set_aligned_position(x+xs/2,y+ys/2,1,1,s); + outtext(s); + } + +typedef struct t_inv_script + { + short col,line; + char *text; + short parm1,parm2; + char lenght; + char align; + }; + +#define INFO_AP -1 +#define INFO_EXP -2 +#define LINE_STEP 6 +#define COL_STEP 8 + +static struct t_inv_script script[]= + { + {15,12,"%d",pvls(VLS_SILA),0,2+128,2}, + {15,14,"%d",pvls(VLS_SMAGIE),0,2+128,2}, + {15,16,"%d",pvls(VLS_POHYB),0,2+128,2}, + {15,18,"%d",pvls(VLS_OBRAT),0,2+128,2}, + {15,5,"%d/%d",offsetof(THUMAN,lives),pvls(VLS_MAXHIT),2,2}, + {15,7,"%d/%d",offsetof(THUMAN,mana),pvls(VLS_MAXMANA),2,2}, + {15,9,"%d/%d",offsetof(THUMAN,kondice),pvls(VLS_KONDIC),2,2}, + {15,20,"%d",offsetof(THUMAN,bonus),0,2,2}, + {15,25,"%d",ptpw(TPW_MEC),0,2,2}, + {15,27,"%d",ptpw(TPW_SEKERA),0,2,2}, + {15,29,"%d",ptpw(TPW_KLADIVO),0,2,2}, + {15,31,"%d",ptpw(TPW_HUL),0,2,2}, + {15,33,"%d",ptpw(TPW_DYKA),0,2,2}, + {15,35,"%d",ptpw(TPW_STRELNA),0,2,2}, + {15,37,"%d",ptpw(TPW_OST),0,2,2}, + {0,0,NULL,0,31,1,0}, + {0,2,NULL,0,30,1,0}, + {15,0,"%d",offsetof(THUMAN,level),0,2,2}, + {30,2,"%d [%d]",offsetof(THUMAN,exp),INFO_EXP,4,2}, + {0,5,NULL,0,14,1,0}, + {0,7,NULL,0,16,1,0}, + {0,9,NULL,0,15,1,0}, + {0,12,NULL,0,10,128,0}, + {0,14,NULL,0,11,128,0}, + {0,16,NULL,0,12,128,0}, + {0,18,NULL,0,13,128,0}, + {0,20,NULL,0,19,0,0}, + {0,23,NULL,0,90,1,0}, + {0,25,NULL,0,91,1,0}, + {0,27,NULL,0,92,1,0}, + {0,29,NULL,0,93,1,0}, + {0,31,NULL,0,94,1,0}, + {0,33,NULL,0,95,1,0}, + {0,35,NULL,0,96,1,0}, + {0,37,NULL,0,97,1,0}, + {30,5,"%d-%d",pvls(VLS_UTOK_L),pvls(VLS_UTOK_H),2,2}, + {30,7,"%d-%d",pvls(VLS_OBRAN_L),pvls(VLS_OBRAN_H),2,2}, + {30,9,"%d",INFO_AP,0,2,2}, + {17,5,NULL,0,18,1,0}, + {17,7,NULL,0,17,1,0}, + {17,9,NULL,0,20,1,0}, + {30,14,"%d",pvls(VLS_OHEN),0,2,2}, + {30,16,"%d",pvls(VLS_VODA),0,2,2}, + {30,18,"%d",pvls(VLS_ZEME),0,2,2}, + {30,20,"%d",pvls(VLS_VZDUCH),0,2,2}, + {30,22,"%d",pvls(VLS_MYSL),0,2,2}, + {17,12,NULL,0,21,1,0}, + {17,14,NULL,0,22,1,0}, + {17,16,NULL,0,23,1,0}, + {17,18,NULL,0,24,1,0}, + {17,20,NULL,0,25,1,0}, + {17,22,NULL,0,26,1,0}, + }; + +static int calc_value(int parm,int lenght) + { + long l; + if (parm>=0) l=*(long *)(((char *)human_selected)+parm); + else + switch (parm) + { + case INFO_EXP: + l=(human_selected->levellevel-1]-human_selected->exp):0); + break; + case INFO_AP: + l=get_ap(human_selected->vlastnosti); + break; + } + switch(lenght) + { + case 1:l=(long)((signed char)l);break; + default: + case 2:l=(long)((short)l);break; + case 4:l=(long)l;break; + } + return l; + } + +void inv_display_vlastnosti() + { + char b; + int i; + + b=human_selected->bonus!=0; + put_picture(INV_DESK,TOP_OFS,ablock(H_SVITEK)); + for(i=0;icol*COL_STEP;y=INV_DESC_Y+scr->line*LINE_STEP; + s=scr->text; + p1=scr->parm1; + p2=scr->parm2; + p1=calc_value(p1,scr->lenght & 0x7f); + if (s==NULL) s=texty[scr->parm2];else p2=calc_value(p2,scr->lenght); + sprintf(buffer,s,p1,p2); + if (scr->lenght & 0x80 && human_selected->bonus) + set_font(H_FONT7,scr->text==NULL?INV_LEVEL_COL1:INV_LEVEL_COL2); + else set_font(H_FONT7,NOSHADOW(0)); + set_aligned_position(x,y,scr->align,0,buffer); + outtext(buffer); + } + set_font(H_FONT7,NOSHADOW(0)); + curcolor=(RGB555(18,17,14)); + percent_bar(INV_DESC_X+140,INV_DESC_Y+170,90,10,human_selected->jidlo,MAX_HLAD(human_selected),texty[69]); + curcolor=(RGB555(14,17,18)); + percent_bar(INV_DESC_X+140,INV_DESC_Y+210,90,10,human_selected->voda,MAX_ZIZEN(human_selected),texty[70]); + if (human_selected->bonus) + for(i=0;i<4;i++) if (calc_value(script[i].parm1,2)<100) + { + int x,y; + x=INV_DESC_X+script[i].col*COL_STEP;y=INV_DESC_Y+script[i].line*LINE_STEP; + set_font(H_FSYMB,RGB555(31,31,31)); + memcpy(charcolors,butt_plus,sizeof(charcolors)); + position(x+1,y);outtext("+"); + } + } + +typedef struct t_info + { + short line,col; + char *format; + short parm1,parm2; + char bonus; + }T_INFO; + + +char muze_nosit(short item) + { + short *p,i,*q,*z; + + p=human_selected->vlastnosti; + q=glob_items[item-1].podminky; + z=glob_items[item-1].zmeny; + for(i=0;i<4;i++) + { + if (*p<*q) return 0; + if (*p+*z<*q) return 0; + q++;z++;p++; + } + return 1; + } + +void hide_inv_info_box() + { + info_box_drawed=0; + if (info_box_below!=NULL) + { + schovej_mysku(); + put_picture(INV_INFO_X-12,INV_INFO_Y-12,info_box_below); + free(info_box_below); + info_box_below=NULL; + ukaz_mysku(); + showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2); + } + } + +void inv_info_box(char *text1,char *text2,char *text3,char asterix) + { + int x,y,ys; + static last_info_ys=0; + ys=INV_INFO_YS; + if (text3!=NULL) ys+=INV_INFO_XP; + if (info_box_below!=NULL && last_info_ys!=ys) + { + put_picture(INV_INFO_X-12,INV_INFO_Y-12,info_box_below); + free(info_box_below); + info_box_below=NULL; + } + last_info_ys=ys; + info_box_drawed=1; + if (info_box_below==NULL) + { + info_box_below=getmem((INV_INFO_XS+28)*(ys+28)*2+6); + get_picture(INV_INFO_X-12,INV_INFO_Y-12,INV_INFO_XS+28,ys+28,info_box_below); + } + x=INV_INFO_X; + y=INV_INFO_Y; + create_frame(x,y,INV_INFO_XS,ys,1); + set_font(H_FBOLD,asterix?(NOSHADOW(RGB555(31,0,0))):NOSHADOW(0)); + position(x,y); + outtext(text1); + position(x,y+12); + outtext(text2); + position(x,y+24); + if (text3!=NULL) outtext(text3); + } + + +static char *get_item_req(char *s,int itn) + { + TITEM *it; + int i; + char *c=s; + + s[0]=0; + itn--;if (itn<0) return NULL; + it=glob_items+itn; + for(i=0;i<4;i++) + if (it->podminky[i]) + { + sprintf(c,texty[200+i],it->podminky[i]); + c=strchr(c,0); + if (i!=3)*c++=32; + } + *c=0; + if (s[0]) return s;else return NULL; + } + +void inv_informuj() + { + int i; + char s[80]; + + if (picked_item==NULL) return; + i=*picked_item; + inv_info_box(glob_items[i-1].jmeno,glob_items[i-1].popis,get_item_req(s,i),!muze_nosit(i)); + } + +void write_pocet_sipu() + { + char s[10]; + if (human_selected->sipy) + { + set_font(H_FBOLD,RGB555(31,31,31)); + sprintf(s,"%d",human_selected->sipy); + set_aligned_position(19,301,1,1,s); + outtext(s); + } + } + + +void redraw_inventory() + { + update_mysky(); + schovej_mysku(); + curcolor=0; + bar(0,16,30,16+360); + bar(620,16,640,16+360); + if (inv_view_mode==0 && ~human_selected->stare_vls[VLS_KOUZLA] & SPL_DEMON && ~human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) display_items_in_inv(human_selected); + else inv_display_vlastnosti(); + display_items_wearing(human_selected); + write_human_big_name(human_selected->jmeno); + write_pocet_sipu(); + display_rings(); + other_draw(); + info_box_drawed=0; + free(info_box_below); + info_box_below=NULL; + ms_last_event.event_type=0x1;send_message(E_MOUSE,&ms_last_event); + ukaz_mysku(); + showview(0,0,0,0); + } + +static void add_vls(int plus,int vls,short *change1,short *change2,float factor) + { + int oldv,newv; + + oldv=(int)(vls*factor); + vls+=plus; + newv=(int)(vls*factor); + if (change1!=NULL) + { + change1[0]+=newv-oldv; + if (change2!=NULL) change2[0]+=newv-oldv; + } + return; + } + +int advance_vls(int id) + { + int i=0; + short *vls=human_selected->stare_vls; + switch (id) + { + case 0:if (vls[VLS_SILA]<100) //max 100 + { + add_vls(1,vls[VLS_SILA],vls+VLS_MAXHIT,&human_selected->lives,1.5f); + add_vls(1,vls[VLS_SILA],vls+VLS_HPREG,NULL,0.08f); + vls[VLS_SILA]++; + i=1; + } + break; + case 1:if (vls[VLS_SMAGIE]<100) //max 100 + { + add_vls(1,vls[VLS_SMAGIE],vls+VLS_MAXMANA,&human_selected->mana,2); + add_vls(1,vls[VLS_SMAGIE],vls+VLS_MPREG,NULL,0.1f); + vls[VLS_SMAGIE]++; + i=1; + } + break; + case 2:if (vls[VLS_POHYB]<100) //max 100 + { + add_vls(1,vls[VLS_POHYB],vls+VLS_MAXHIT,&human_selected->lives,0.5); + add_vls(1,vls[VLS_POHYB],vls+VLS_KONDIC,&human_selected->kondice,0.25); + vls[VLS_POHYB]++; + i=1; + } + break; + case 3:if (vls[VLS_OBRAT]<100) //max 100 + { + add_vls(1,vls[VLS_OBRAT],vls+VLS_KONDIC,&human_selected->kondice,0.5); + add_vls(1,vls[VLS_OBRAT],vls+VLS_VPREG,NULL,0.1f); + vls[VLS_OBRAT]++; + i=1; + } + break; + } + return i; + } + +static void timed_redraw(THE_TIMER *t) + { + t; + bott_draw(1); + inv_redraw(); + } + +char vls_click(int id,int xa,int ya,int xr,int yr) + { + int xs,ys,i; + + if (!human_selected->bonus) return 0; + set_font(H_FSYMB,0); + xs=text_width("+"); + ys=text_height("+"); + for(id=0;id<4;id++) + { + int xe,ye; + float mh,mv; + xr=INV_DESC_X+COL_STEP*script[id].col+1; + yr=INV_DESC_Y+LINE_STEP*script[id].line; + xe=xr+xs;ye=yr+ys; + if (xa>=xr && xa=yr && yajidlo/MAX_HLAD(human_selected); + mv=(float)human_selected->voda/MAX_ZIZEN(human_selected); + i=advance_vls(id); + if (i>0) + { + schovej_mysku(); + set_font(H_FSYMB,0x0); + memcpy(charcolors,butt_plus,sizeof(butt_plus)); + charcolors[1]=butt_plus[3]; + charcolors[3]=butt_plus[1]; + position(xr,yr);outtext("+"); + ukaz_mysku(); + showview(xr,yr,xs,ys); + } + human_selected->bonus-=i; + prepocitat_postavu(human_selected); + human_selected->jidlo=(int)(mh*MAX_HLAD(human_selected)); + human_selected->voda=(int)(mv*MAX_ZIZEN(human_selected)); + add_to_timer(-1,6,1,timed_redraw); + } + } + return 1; + } + + + +void inv_item_info_box(EVENT_MSG *msg,void **data) + { + MS_EVENT *ms; + char podm; + int pos; + static int lastpos=-1; + int xr,yr; + + data; + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (picked_item!=NULL) + { + if (ms->y>378 && info_box_drawed) hide_inv_info_box(); + else if (ms->y<=378 && !info_box_drawed) + { + schovej_mysku(); + inv_informuj(); + ukaz_mysku(); + showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2); + } + lastpos=-1; + } + else + { + if (inv_view_mode) return; + podm=(ms->x>=clk_inv_view[0].xlu && + ms->x<=clk_inv_view[0].xrb && + ms->y>=clk_inv_view[0].ylu && + ms->y<=clk_inv_view[0].yrb); + xr=ms->x-clk_inv_view[0].xlu; + yr=ms->y-clk_inv_view[0].ylu; + if (podm) pos=(xr/INV_XS)+6*(yr/INV_YS);else pos=-1; + if (pos>=human_selected->inv_size) podm=0; + if (podm && (!info_box_drawed || pos!=lastpos)) + { + int i=human_selected->inv[pos]; + if (i) + { + char s[80]; + schovej_mysku(); + inv_info_box(glob_items[i-1].jmeno,glob_items[i-1].popis,get_item_req(s,i),!muze_nosit(i)); + showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2); + ukaz_mysku(); + } + else if (info_box_drawed) hide_inv_info_box(); + } + else if (!podm && info_box_drawed) hide_inv_info_box(); + lastpos=pos; + } + } + } + +void unwire_inv_mode() + { + send_message(E_DONE,E_KEYBOARD,inv_keyboard); + send_message(E_DONE,E_MOUSE,inv_item_info_box); + build_all_players(); + } + +char vejdou_se(int pocet) + { + int i=human_selected->inv_size-1; + + while (i>=0) if (!human_selected->inv[i--]) pocet--; + return pocet>0; + } + +char uloz_sip(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya;xr;yr; + + if (isdemon(human_selected)) return 0; + if (neprezbrojit()) return 0; + if (picked_item!=NULL && picked_item[1]==0 && glob_items[picked_item[0]-1].umisteni==PL_SIP) + { + int pocet=glob_items[picked_item[0]-1].user_value; + if (pocet==0) pocet=1; + if (human_selected->sipy+pocet>99) return 1; + human_selected->sipy+=pocet; + free(picked_item); + picked_item=NULL; + } + else + if (picked_item==NULL && human_selected->sipy) + { + short x[2]; + int i; + + for(i=0;isipy--; + break; + } + } + pick_set_cursor(); + inv_redraw(); + return 1; + } + +static char MakeItemCombinations(short *itm1, short *itm2) +{ + short i1=*itm1-1,i2=*itm2-1; + char *fname; + int src1; + int src2; + int trg1; + int trg2; + int cnt; + char succ=0; + + FILE *table; + + concat(fname,pathtable[SR_MAP],"COMBITEM.DAT"); + table=fopen(fname,"r"); + if (table==0 && pathtable[SR_MAP2][0]) + { + concat(fname,pathtable[SR_MAP2],fname); + table=fopen(table,"r"); + } + if (table==0) return 0; + cnt=fscanf(table,"%d %d -> %d %d",&src1,&src2,&trg1,&trg2); + while(cnt>=3) + { + if (src1==i1 && src2==i2) + { + if (cnt==3) + { + *itm2=trg1+1; + *itm1=0; + } + else + { + *itm1=trg1+1; + *itm2=trg2+1; + } + succ=1; + break; + } + if (src1==i2 && src2==i1) + { + if (cnt==3) + { + *itm2=trg1+1; + *itm1=0; + } + else + { + *itm2=trg1+1; + *itm1=trg2+1; + } + succ=1; + break; + } + if (fscanf(table," ;")==-1) break; + cnt=fscanf(table,"%d %d -> %d %d",&src1,&src2,&trg1,&trg2); + } + fclose(table); + return succ; +} + +char bag_click(int id,int xa,int ya,int xr,int yr) + { + short p,*pk; + + if (inv_view_mode || human_selected->stare_vls[VLS_KOUZLA] & SPL_DEMON || human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) return vls_click(id,xa,ya,xr,yr); + xa;ya; + id=(xr/INV_XS)+6*(yr/INV_YS); + if (id>=human_selected->inv_size) return 0; + pk=picked_item; + if (pk!=NULL) + { + if (picked_item[1]!=0 && vejdou_se(count_items_total(picked_item))) return 0; + if (picked_item[1]!=0 || human_selected->inv[id]==0 || !MakeItemCombinations(picked_item,human_selected->inv+id)) + while (*pk) + { + p=human_selected->inv[id]; + human_selected->inv[id]=abs(*pk); + *pk=p;pk++; + if (*pk) while (human_selected->inv[id]) if ((++id)>=human_selected->inv_size) id=0; + } + } + else + { + picked_item=getmem(2*sizeof(short)); + picked_item[0]=human_selected->inv[id]; + picked_item[1]=0; + human_selected->inv[id]=0; + } + if (!picked_item[0]) + { + free(picked_item); + picked_item=NULL; + } + pick_set_cursor(); + play_sample_at_channel(H_SND_PUTINV,0,100); + inv_redraw(); + return 1; + } + +char item_pointed(int k,int x,int y,short item,short kind) + { + int x1,y1,x2,y2,xs,ys,xsiz,ysiz,i; + short *p; + char *c,cc; + + if (!item) return 0; + i=glob_items[item-1].vzhled; + p=ablock(i+face_arr[1+kind]); + xs=glob_items[item-1].polohy[k][0]+HUMAN_X+PO_XSS; + ys=HUMAN_Y-glob_items[item-1].polohy[k][1]-20; + xsiz=p[0]>>1; + ysiz=p[1]; + x1=xs-xsiz;y1=ys-ysiz; + x2=xs+xsiz;y2=ys; + if (x>=x1 && x<=x2 && y>=y1 && y<=y2) + { + xs=x-x1; + ys=y-y1; + c=(char *)p;c+=PIC_FADE_PAL_SIZE+xs+ys*p[0]; + cc=*c; + } + else cc=0; + return cc!=0; + } + +char inv_swap_desk(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + inv_view_mode=!inv_view_mode; + inv_redraw(); + return 1; + } + +char ring_place(int id,int xa,int ya,int xr,int yr) + { + short ring; + + xa,ya,xr,yr; + if (neprezbrojit()) return 0; + if (isdemon(human_selected)) return 0; + if (human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) return 0; + ring=human_selected->prsteny[id]; + if (picked_item==NULL) + if (ring) + { + picked_item=(short *)getmem(2*sizeof(short)); + picked_item[0]=ring; + picked_item[1]=0; + human_selected->prsteny[id]=0; + } + else return 0; + else + if (picked_item[1]==0) + { + int i; + + i=picked_item[0]-1; + if (glob_items[i].umisteni!=PL_PRSTEN) return 1; + human_selected->prsteny[id]=picked_item[0]; + *picked_item=ring; + if (!ring) + { + free(picked_item);picked_item=0; + } + } + prepocitat_postavu(human_selected); + zkontroluj_postavu(); + pick_set_cursor(); + inv_redraw(); + return 1; + } + + +void vymen_batohy() + { + short *old,*c; + int i; + + c=old=(short *)getmem(sizeof(short)*40); + memset(old,0,sizeof(short)*40); + *c++=human_selected->wearing[PO_BATOH]; + for(i=6;iinv_size;i++) + { + *c=-human_selected->inv[i]; + if (*c) c++; + } + for(i=6;iinv[i]=0; + if (picked_item!=NULL) + { + int it; + + c=picked_item; + it=human_selected->wearing[PO_BATOH]=*c++; + i=6; + while (*c && iinv[i++]=-*c++; + human_selected->inv_size=glob_items[it-1].nosnost+6; + } + else + { + human_selected->inv_size=6; + human_selected->wearing[PO_BATOH]=0; + } + if (old[0]) picked_item=old; + else + { + free(old); + picked_item=NULL; + } + prepocitat_postavu(human_selected); + zkontroluj_postavu(); + pick_set_cursor(); + play_sample_at_channel(H_SND_WEAR,1,100); + inv_redraw(); + } + +void remove_item(THUMAN *p,int what) + { + if (p->wearing[what]) + { + int i; + short z[2]; + + z[0]=p->wearing[what]; + z[1]=0; + if (glob_items[z[0]-1].flags & ITF_NOREMOVE) destroy_items(z); + else + { + for(i=0;iinv_size && p->inv[i];i++); + if (i!=p->inv_size) p->inv[i]=p->wearing[what]; + else push_item(p->sektor,p->direction,z); + } + p->wearing[what]=0; + } + } + +int calculate_weight(THUMAN *p) +{ + int suma=0; + int i; + for (i=0;iinv_size;i++) if (p->inv[i]) + suma+=glob_items[p->inv[i]-1].hmotnost; + suma=suma*3/2; + for (i=0;iwearing[i]) + suma+=glob_items[p->wearing[i]-1].hmotnost; + for (i=0;iprsteny[i]) + suma+=glob_items[p->prsteny[i]-1].hmotnost; + return suma; +} + + +int weigth_defect(THUMAN *p) +{ + int wh,wf; + wh=calculate_weight(p); + if (wh>p->vlastnosti[VLS_SILA]*20) + wf=(wh-p->vlastnosti[VLS_SILA]*20)/200; + else + wf=0; + return wf; +} + +static char check_double_wield(int newplace,short item) + { + short *p,i,*q1,*q2; + short *z1,*z2; + short opplace=newplace==PO_RUKA_L?PO_RUKA_R:PO_RUKA_L; + short item2=human_selected->wearing[opplace]; + + if (!item || !item2) return 0; + if (glob_items[item-1].druh!=TYP_UTOC || glob_items[item2-1].druh!=TYP_UTOC ) return 0; + p=human_selected->vlastnosti; + q1=glob_items[item-1].podminky; + q2=glob_items[item2-1].podminky; + z1=glob_items[item-1].zmeny; + z2=glob_items[item2-1].zmeny; + for(i=0;i<4;i++) + { + int chk=(*q1+*q2)*3/4; + if (*pwearing; + for(i=0;iwearing[PO_RUKA_R])) + remove_item(human_selected,PO_RUKA_L); + } + + + +char human_click(int id,int xa,int ya,int xr,int yr) + { + short itsave=0; + short place=-1; + short um=0; + + + xr;yr;id; + if (battle && (battle_mode!=MD_PREZBROJIT || select_player!=human_selected-postavy) || human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) return 0; + if (isdemon(human_selected)) return 0; + if (picked_item!=NULL) + if (muze_nosit(*picked_item)) + if (glob_items[(*picked_item)-1].umisteni==PL_BATOH) + { + vymen_batohy(); + return 0; + } + else if (picked_item[1]!=0) return 0; + else + { + um=place=glob_items[picked_item[0]-1].umisteni; + if (!place) + { + switch (glob_items[picked_item[0]-1].druh) + { + case TYP_LEKTVAR:inv_quaf(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break; + case TYP_JIDLO:inv_najist(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break; + case TYP_VODA:inv_napit(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break; + case TYP_SPECIALNI:inv_use_spec(&picked_item);break; + } + inv_redraw(); + return 1; + } + if (place==PL_RUKA) + if (xr<94) place=PO_RUKA_R;else place=PO_RUKA_L; + else if (place==PL_OBOUR) place=PO_RUKA_R; + else place--; + if (place>=HUMAN_PLACES) return 0; + itsave=human_selected->wearing[place]; + } + else return 0; + else + { + int i=HUMAN_PLACES-1; + while (i>=0) + { + if (item_pointed(i==PO_RUKA_L,xa,ya,human_selected->wearing[i],human_selected->female)) break; + i--; + } + if (i<0) return 0; + if (i==PO_BATOH) vymen_batohy(); + else + { + picked_item=getmem(2*sizeof(short)); + picked_item[0]=human_selected->wearing[i]; + picked_item[1]=0; + human_selected->wearing[i]=0; + } + } + if (um) + { + switch (um) + { + case PL_KUTNA:remove_item(human_selected,PO_HLAVA); + remove_item(human_selected,PO_TELO_D); + remove_item(human_selected,PO_TELO_H); + break; + case PL_OBOUR:remove_item(human_selected,PO_RUKA_L); + break; + case PL_TELO_H: + case PL_TELO_D: + case PL_HLAVA:remove_item(human_selected,PO_KUTNA); + break; + case PL_RUKA :if (place==PO_RUKA_L) + if (human_selected->wearing[PO_RUKA_R] && glob_items[human_selected->wearing[PO_RUKA_R]-1].umisteni==PL_OBOUR) + remove_item(human_selected,PO_RUKA_R); + if (check_double_wield(place,*picked_item)) + remove_item(human_selected,place==PO_RUKA_L?PO_RUKA_R:PO_RUKA_L); + break; + } + human_selected->wearing[place]=*picked_item; + if (itsave) *picked_item=itsave; + else + { + free(picked_item);picked_item=NULL; + } + } + if (picked_item!=NULL && glob_items[*picked_item-1].flags & ITF_NOREMOVE) + { + destroy_items(picked_item); + free(picked_item); + picked_item=NULL; + } + play_sample_at_channel(H_SND_WEAR,1,100); + prepocitat_postavu(human_selected); + zkontroluj_postavu(); + pick_set_cursor(); + inv_redraw(); + return 1; + } + + +void *inv_keyboard(EVENT_MSG *msg,void **usr) + { + char c; + + usr; + if (msg->msg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + switch (c) + { + case 0x17: + case 1:unwire_inv_mode(); + wire_proc(); + inv_view_mode=0; + break; + case 28: + case 15: + case 50: + if (GlobEvent(MAGLOB_BEFOREMAPOPEN,viewsector,viewdir)) + { + unwire_inv_mode(); + show_automap(1); + } + break; + } + } + return &inv_keyboard; + } + + +void wire_inv_mode(THUMAN *select) + { + mute_all_tracks(0); + send_message(E_ADD,E_KEYBOARD,inv_keyboard); + change_click_map(clk_inv_view,CLK_INV_VIEW); + send_message(E_ADD,E_MOUSE,inv_item_info_box); + human_selected=select; + if (human_selected->bonus!=0 && picked_item==NULL) inv_view_mode=1; + cur_mode=MD_INV; + build_all_players(); + redraw_inventory(); + unwire_proc=unwire_inv_mode; + inv_redraw=redraw_inventory; + } + +static LETICI_VEC *fly_map=NULL; +static int fly_map_size=0; //velikost mapy +static int fly_count; //vyuziti mapy + +void draw_fly_items(int celx,int cely,int sector,int side) + { + LETICI_VEC *p; + int xpos,ypos; + short *pic,picnum;char turn,smr; + TITEM *it; + int i; + + p=fly_map; + if (map_coord[sector].flags & 2) + { + i=fly_count; + while (i--) + if (p->sector==sector && (p->items!=NULL || p->item!=0)) + { + switch(smr=(p->smer-side)&0x3) + { + case 0: xpos=p->ypos;ypos=p->xpos;turn=(celx*128+xpos)<0;break; + case 1: xpos=p->xpos;ypos=-p->ypos;turn=1;break; + case 2: xpos=-p->ypos;ypos=-p->xpos;turn=(celx*128+xpos)<0;break; + case 3: xpos=-p->xpos;ypos=p->ypos;turn=0;break; + } + xpos+=64; + ypos+=64; + if (p->items==NULL) it=glob_items+p->item-1;else it=&glob_items[*(p->items)-1]; + if (p->flags & FLY_DESTROY_SEQ) smr=3; + else if (smr==3) smr=1; + picnum=it->v_letu[(smr<<2)+p->anim_pos]; + if (!picnum) + if (it->vzhled) + picnum=it->vzhled+face_arr[0]; + else + picnum=0; + else picnum+=face_arr[3]; + if (picnum) + { + pic=ablock(picnum); + draw_placed_texture(pic,celx,cely,xpos,ypos,p->zpos,turn); + } + p++; + } + else p++; + } + } + +void build_fly_map() + { + LETICI_VEC *p,*p2; + static int counter=0; + + fly_count=0; + for(p=letici_veci;p!=NULL;p=p->next) if (!(p->flags & (FLY_BURNT|FLY_UNUSED))) fly_count++; + if (fly_count>fly_map_size || !counter) + { + free(fly_map);fly_map=NewArr(LETICI_VEC,fly_count); + if (!counter) + SEND_LOG("(FLY) Fly_map was reduced - capacity: %d flies in game / was: %d",fly_count,fly_map_size); + else + SEND_LOG("(FLY) Fly_map was expanded - capacity: %d flies in game ",fly_count,fly_map_size); + counter=1000; + fly_map_size=fly_count; + } + else counter--; + for(p=letici_veci,p2=fly_map;p!=NULL;p=p->next) if (!(p->flags & (FLY_BURNT|FLY_UNUSED))) + { + map_coord[p->sector].flags|=2; + p->anim_pos++;p->anim_pos&=3; + memcpy(p2,p,sizeof(LETICI_VEC)); + if (p->flags & FLY_DESTROY_SEQ && p->anim_pos==3) + { + stop_fly(p,1); + } + p2++; + } + else + p->flags|=FLY_UNUSED; + } + +void destroy_fly_map() + { + int i; + LETICI_VEC *f; + + for(i=0,f=fly_map;isector].flags &=~MC_FLY; + fly_count=0; + } + + + +void add_fly(LETICI_VEC *p) + { + + p->next=letici_veci; + letici_veci=p; + } + + +LETICI_VEC *throw_fly(int x,int y, char rovne) + { + LETICI_VEC *p; + int m; + + p=create_fly(); + p->zpos=128-y*128/360; + p->ypos=(x>320)?32:-32; + p->sector=viewsector; + p->smer=viewdir; + p->items=picked_item; + p->counter=0; + p->hit_bonus=0; + p->damage=0; + m=abs(celkova_vaha(picked_item)); + if (mglob.map_effector==ME_PVODA) m+=50; + p->flags=(rovne?FLY_NEHMOTNA:0) | (glob_items[*picked_item-1].flags & ITF_DESTROY?FLY_DESTROY:0); + if (m) p->speed=1000/(m)+1;else p->speed=24; + if (p->speed>56) p->speed=56; + p->xpos=p->speed+1; + p->velocity=-(360-y)/72; + if (rovne) p->velocity=0; + if (select_player==-1 || !battle) p->owner=postavy-human_selected+1; + else p->owner=select_player+1; + p->hit_bonus=0; + add_fly(p); + picked_item=NULL; + if (!battle) pick_set_cursor(); + return p; + } + +void build_all_players() + { + int i; + + for(i=0;imsg==E_MOUSE) + { + MS_EVENT *ms; + int x,y; + char cc=1; + static last_pos=-1; + + ms=get_mouse(msg); + x=ms->x-(BUYBOX_X+SHP_ICPLCX); + y=ms->y-(BUYBOX_Y+SHP_ICPLCY); + if (picked_item==NULL && x>0 && y>0 && x<(4*SHP_ICSIZX) && y<(2*SHP_ICSIZY)) + { + int i,j; + x/=SHP_ICSIZX; + y/=SHP_ICSIZY; + i=4*y+x; + if (i<8 && (j=shp_item_map[i])!=0 && i!=last_pos) + { + char c[80]; + char s[80]; + int cena=cur_shop->list[shp_item_pos[i]].cena; + + j--; + schovej_mysku(); + sprintf(c,"%s (%d)",glob_items[j].jmeno,cena+cur_shop->koef*cena/100); + inv_info_box(c,glob_items[j].popis,get_item_req(s,j+1),!muze_nosit(j+1)); + ukaz_mysku(); + showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2); + last_pos=i; + cc=0; + } + else cc=i!=last_pos; + } + if (cc) + { + inv_item_info_box(msg,unused); + last_pos=-1; + } + } + } +static void rebuild_shops(void) + { + char *c=(char *)shop_hacek; + int i; + + SEND_LOG("(SHOP) Rebuilding shops....",0,0); + if (shop_list!=NULL) free(shop_list); + shop_list=NewArr(TSHOP *,max_shops); + c+=4; + for(i=0;ilist=(TPRODUCT *)c; + c+=p->products*sizeof(TPRODUCT); + SEND_LOG("(SHOP) Shop found: '%s'",p->keeper,0); + } + } + +void load_shops(void) + { + char *c; + int *d; + if (!test_file_exist(SR_MAP,SHOP_NAME)) + { + shop_hacek=NULL; + shop_list=NULL; + return; + } + shop_hacek=afile(SHOP_NAME,SR_MAP,&shop_hacek_size); + d=shop_hacek;c=shop_hacek; + max_shops=*d; + if (!max_shops) + { + free(shop_hacek); + shop_hacek=NULL; + shop_list=NULL; + return; + } + rebuild_shops(); + } + +static void rebuild_keepers_items() + { + int i; + TPRODUCT *p; + int remain; + char c; + + memset(shp_item_map,0,sizeof(shp_item_map)); + memset(shp_item_pos,0,sizeof(shp_item_map)); + do + { + remain=cur_shop->list_size-top_item; + p=cur_shop->list+top_item; + for(i=0;i<8 && remain>0;remain--,p++) + if (p->trade_flags & SHP_SELL && p->pocet) + { + shp_item_pos[i]=p-cur_shop->list; + shp_item_map[i++]=p->item+1; + } + c=(i<8 && top_item); + if (c) top_item--; + } + while (c); + } + +static int make_offer(int i) + { + int j; + i--; + for(j=0;jlist_size;j++) + { + TPRODUCT *p=cur_shop->list+j; + if (p->item==i && p->trade_flags & SHP_BUY) return p->cena-(p->cena*cur_shop->koef/100); + } + return 0; + } + +static int get_sell_price(int i) //cislo predmetu + { + int j; + i--; + for(j=0;jlist_size;j++) + { + TPRODUCT *p=cur_shop->list+j; + if (p->item==i && p->trade_flags & SHP_SELL && p->pocet>0) return p->cena+(p->cena*cur_shop->koef/100); + } + return 0; + } + +static TPRODUCT *find_sell_product(int i) //cislo predmetu + { + int j; + i--; + for(j=0;jlist_size;j++) + { + TPRODUCT *p=cur_shop->list+j; + if (p->item==i) return p; + } + return NULL; + } + + +static void sell_item(int i) + { + int j; + i--; + for(j=0;jlist_size;j++) + { + TPRODUCT *p=cur_shop->list+j; + if (p->item==i) + { + p->pocet--; + return; + } + } + } + +static void buy_item(int i) + { + int j; + i--; + for(j=0;jlist_size;j++) + { + TPRODUCT *p=cur_shop->list+j; + if (p->item==i) + { + p->pocet++; + return; + } + } + } + +static void display_keepers_items() + { + int x,y,i; + put_picture(BUYBOX_X,BUYBOX_Y,ablock(H_SHOP_PIC)); + i=0; + for(y=0;y<2*SHP_ICSIZY;y+=SHP_ICSIZY) + for(x=0;x<4*SHP_ICSIZX;x+=SHP_ICSIZX) + if (shp_item_map[i]) + { + int ikn; + + ikn=glob_items[shp_item_map[i++]-1].ikona; + put_picture(BUYBOX_X+SHP_ICPLCX+x,BUYBOX_Y+SHP_ICPLCY+y,ico_extract(ikn)); + } + else + i++; + set_font(H_FBOLD,INV_NAME_COL); + set_aligned_position(135+BUYBOX_X,17+BUYBOX_Y,1,1,cur_shop->keeper); + outtext(cur_shop->keeper); + } + +static void redraw_shop() + { + update_mysky(); + schovej_mysku(); + curcolor=0; + display_items_in_inv(human_selected); + display_keepers_items(); + //write_shopkeeper_name(cur_shop->keeper); + other_draw(); + info_box_drawed=0; + if (info_box_below!=NULL) free(info_box_below); + info_box_below=NULL; + ms_last_event.event_type=0x1;send_message(E_MOUSE,&ms_last_event); + ukaz_mysku(); + showview(0,0,0,0); + } + + + +static void block_next() + { + TPRODUCT *p=cur_shop->list+top_item; + int remain=cur_shop->list_size-top_item; + int i,j; + + if (remain<8) return; + j=top_item; + for(i=0;i<8 && remain>0;j++,remain--,p++) if (p->pocet && p->trade_flags & SHP_SELL) i++; + if (i!=8 || !remain) return; + top_item=j; + } + +static void block_back() + { + TPRODUCT *p=cur_shop->list+top_item; + int i,j; + + + if (top_item<8) top_item=0; + else + { + j=top_item; + for(i=0;i<8 && j>0;j--,p--) if (p->pocet && p->trade_flags & SHP_SELL) i++; + if (i==8) top_item=j; else top_item=0; + } + return; + } + +static void redraw_keepers_items() + { + word *w; + schovej_mysku(); + w=ablock(H_SHOP_PIC); + display_keepers_items(); + ukaz_mysku(); + showview(BUYBOX_X,BUYBOX_Y,w[0],w[1]); + } + +static char shop_keeper_click(int id, int xa, int ya,int xr,int yr) + { + id;xa;ya; + if (picked_item==NULL) + { + int i,j; + xr=(xa-BUYBOX_X-SHP_ICPLCX); + yr=(ya-BUYBOX_Y-SHP_ICPLCY); + if (xr<0 || yr<0) return 0; + xr/=SHP_ICSIZX; + yr/=SHP_ICSIZY; + i=yr*4+xr; + if (i<8 && i>=0 && (j=shp_item_map[i])!=0) + { + picked_item=NewArr(short,2); + picked_item[0]=shp_item_map[i]; + picked_item[1]=0; + shp_item_map[i]=0; + cur_owner=-1; + schovej_mysku(); + pick_set_cursor(); + redraw_keepers_items(); + ukaz_mysku(); + update_mysky(); + if ((GetKeyState(VK_CONTROL) & 0x80) && (game_extras & EX_FAST_TRADE) && get_sell_price(*picked_item)<=money) + { + play_sample_at_channel(H_SND_OBCHOD,1,100); + money-=get_sell_price(*picked_item); + sell_item(*picked_item); + if (put_item_to_inv(human_selected,picked_item)) + { + picked_item=NULL; + pick_set_cursor(); + } + rebuild_keepers_items(); + cur_owner=picked_item!=NULL; + redraw_shop(); + } + return 1; + } + } + else + if (cur_owner==-1) + { + free(picked_item); + picked_item=NULL; + rebuild_keepers_items(); + schovej_mysku(); + pick_set_cursor(); + redraw_keepers_items(); + ukaz_mysku(); + update_mysky(); + cur_owner=0; + return 1; + } + if (cur_owner!=-1 && picked_item!=NULL) + { + int price,z; + char c[200]; + mouse_set_cursor(H_MS_DEFAULT); + if (picked_item[1]!=0) + { + message(1,0,0,"",texty[100],texty[80]); + wire_shop(); + } + else + { + price=make_offer(z=picked_item[0]); + if (!price) + { + sprintf(c,texty[103],glob_items[z-1].jmeno); + message(1,0,0,"",c,texty[80]); + wire_shop(); + } + else + { + int p;TPRODUCT *pp; + + pp=find_sell_product(z); + sprintf(c,texty[102],price); + p=message(3,0,1,texty[118],c,texty[77],texty[230],texty[78]); + if (p==2) price=-1; + if (p==1) price=smlouvat(price,pp->cena,pp->pocet,money,0); + if (price>=0) + { + play_sample_at_channel(H_SND_OBCHOD,1,100); + buy_item(z); + free(picked_item);picked_item=NULL; + money+=price; + rebuild_keepers_items(); + } + wire_shop(); + } + } + pick_set_cursor(); + update_mysky(); + return 1; + } + return 0; + } + + +static char shop_bag_click(int id,int xa,int ya,int xr,int yr) + { + char s[200],p; + int price,z; + TPRODUCT *pp; + if (cur_owner>-1) + { + id=bag_click(id,xa,ya,xr,yr); + cur_owner=picked_item!=NULL; + if (picked_item!=NULL && picked_item[1]==0 && (game_extras & EX_FAST_TRADE) && (GetKeyState(VK_CONTROL) & 0x80)) + { + short z; + price=make_offer(z=picked_item[0]); + if (price) + { + play_sample_at_channel(H_SND_OBCHOD,1,100); + buy_item(z); + free(picked_item);picked_item=NULL; + money+=price; + rebuild_keepers_items(); + pick_set_cursor(); + redraw_shop(); + } + } + return id; + } + if (picked_item==NULL) return 0; + z=picked_item[0]; + price=get_sell_price(z); + pp=find_sell_product(z); + if (pp==NULL) return 0; + mouse_set_cursor(H_MS_DEFAULT); + if (!price) return 0; + if (price>money) + { + p=message(2,0,0,"",texty[104],texty[230],texty[78]); + if (!p) price=smlouvat(price,pp->cena,pp->pocet,money,1);else price=-1; + } + else + { + sprintf(s,texty[101],price); + p=message(3,0,1,texty[118],s,texty[77],texty[230],texty[78]); + if (p==1) price=smlouvat(price,pp->cena,pp->pocet,money,1);else + if (p==2) price=-1; + } + if (price>=0) + { + play_sample_at_channel(H_SND_OBCHOD,1,100); + money-=price; + sell_item(z); + rebuild_keepers_items(); + id=bag_click(id,xa,ya,xr,yr); + cur_owner=picked_item!=NULL; + } + else + { + shop_keeper_click(0,0,0,0,0); + } + wire_shop(); + return 1; + } + +static char shop_block_click(int id, int xa, int ya,int xr,int yr) + { + xa,ya,xr,yr; + if (id==1) block_back();else block_next(); + rebuild_keepers_items(); + redraw_keepers_items(); + return 1; + } + + +static int old_inv_view_mode; + +void unwire_shop() + { + send_message(E_DONE,E_MOUSE,shop_mouse_event); + norefresh=0; + wire_proc=wire_shop; + inv_view_mode=old_inv_view_mode; + } + +void wire_shop() + { + long size; + static TSHOP *last_shop=NULL; + static void *pic=NULL; + mute_all_tracks(0); + old_inv_view_mode=inv_view_mode; + inv_view_mode=0; + inv_redraw=redraw_shop; + schovej_mysku(); + if (last_shop!=cur_shop) + { + free(pic);pic=afile(cur_shop->picture,SR_DIALOGS,&size); + last_shop=cur_shop; + } + if (cur_shop->picture[0]) put_picture(5,SCREEN_OFFLINE,pic); + send_message(E_ADD,E_MOUSE,shop_mouse_event); + unwire_proc=unwire_shop; + change_click_map(clk_shop,CLK_SHOP); + if (shop_sector==viewsector) redraw_shop();else _exit_shop(0,0,0,0,0); + ukaz_mysku(); + update_mysky(); + } + +void enter_shop(int shopid) + { + int i; + + SEND_LOG("(SHOP) Entering shop...",0,0); + for(i=0;ishop_id==shopid) break; + if (i==max_shops) return; + unwire_proc(); + cur_shop=shop_list[i]; + curcolor=0; + bar(0,0,639,479); + rebuild_keepers_items(); + bott_draw(1); + shop_sector=viewsector; + wire_shop(); + cancel_render=1; + cancel_pass=1; + norefresh=1; + cur_mode=MD_SHOP; + } + + word *xs; + +char shop_change_player(int id, int xa, int ya,int xr,int yr) + { + word *xs; + int i; + + id;xa;ya;yr; + xs=ablock(H_OKNO); + i=xr/xs[0]; + if (iused && p->sektor==viewsector) + if (ms_last_event.event_type & 0x2) + { + int j=select_player; + select_player=i; + human_selected=p; + if (i==j && cur_owner>-1) + { + unwire_proc(); + wire_inv_mode(p); + } + else + { + bott_draw(1); + redraw_shop(); + } + } + else if (picked_item!=NULL && cur_owner>-1) + { + if (put_item_to_inv(p,picked_item)) + { + free(picked_item);picked_item=NULL; + pick_set_cursor(); + redraw_shop(); + } + } + else if (picked_item==NULL) _exit_shop(id,xa,ya,xr,yr); + + return 1; + } + return 0; + } + +char _exit_shop(int id, int xa, int ya,int xr,int yr) + { + xr,yr,xa,ya,id; + SEND_LOG("(SHOP) Exiting shop...",0,0); + if (cur_owner==-1) + { + free(picked_item); + picked_item=NULL; + pick_set_cursor(); + } + unwire_proc(); + wire_main_functs(); + return 1; + } + + +static void reroll_shop(TSHOP *p) + { + int i,j,r; + int poc_spec=0; + TPRODUCT *pr; + + SEND_LOG("(SHOP) Shops reroll: '%s' ",p->keeper,0); + pr=p->list; + for(i=0;ilist_size;i++,pr++) + { + if (pr->trade_flags & SHP_AUTOADD && pr->pocetmax_pocet) pr->pocet++; + if (pr->trade_flags & SHP_SPECIAL) + { + poc_spec++;if (pr->pocet>0) pr->pocet=0; + } + } + pr=p->list; + for(i=0;ispec_max;i++) + { + int i=0; + r=rnd(poc_spec)+1; + for(j=0;i +/* + + Popis jazyka pro psani textu do knihy + + + [cislo] + + .... text + .... + + [/cislo] + + + Tagy + +

paragraph +
break line + +


horizontal rule + page end + + + + ----------------------------- + + Vnitrni zapis + + Escape sekvence + + ESC s - mezera n bodu + ESC p obrazek na souradnicich x a y + ESC e - konec stranky (jako prvni v textu) + ESC h - horizontalni rule (jako prvni v textu) + ESC l - konec radky (skip je pocet vynechanych bodu) + + Zapis cisla - to je hexa cislo od 1-255 pokud se nevejde do rozsahu je po 256 + pridana dalsi hodnota, tj 255 se zapise jako 255,1, + 350 se zapise jako 255,96, + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +#define XMAX 254 +#define YMAX 390 +#define XLEFT 34 +#define YLEFT 50 +#define XRIGHT 354 + +#define PARAGRAPH "P" +#define BREAKLINE "BR" +#define IMAGE "IMG" +#define HOR_RULE "HR" +#define CENTER1 "CENTER" +#define CENTER2 "/CENTER" +#define DISTEND1 "DISTEND" +#define DISTEND2 "/DISTEND" +#define ALIGN "ALIGN" +#define PIC_LINE "LINE" +#define PIC_LSIZ "LSIZE" +#define SRC "SRC" + +#define ALEFT "LEFT" +#define ARIGHT "RIGHT" +#define ACENTER "CENTER" + +#define ANUM_LEFT 1 +#define ANUM_RIGHT 2 +#define ANUM_CENTER 0 + +#define END_PAGE 'e' +#define SPACE 's' +#define PICTURE 'p' +#define HRUL 'h' +#define END_LINE 'l' + +#define BOOK_FILE "_BOOK.TMP" + +static int center=0; +static int distend=0; +static TSTR_LIST all_text=NULL; +static char read_buff[256]; +static char write_buff[256]; +static int buff_pos=0; +static int buff_end=0; +static int total_width=XMAX; +static int left_skip=0; +static int linepos=0,last_skip=1; +static int picture_len=0; +static char winconv=0; +static int relpos=0; + +static char xlat_table[128]="›__†’_____­_____¨__ź‘__________________________________Ź___Š__€__‰‹_…__Ą•____ž¦—__ť___ ___Ť__‡‚__ˇ___¤˘____©–Ł__"; + +static int insert_num(char *text,int pos,int num) + { + char c=0x80; + do + { + c=num & 0x3f;num>>=6; + if (num) c|=0x80; + c|=0x40; + text[pos++]=c; + } + while (num); + return pos; + } + + +static int read_num(char *text,int *pos) + { + int num=0,shift=0; + char c; + + do + { + c=text[pos[0]++]; + num|=(c & 0x3f)<YMAX) + { + char s[3]; + s[0]=27; + s[1]=END_PAGE; + s[2]=0; + str_add(&all_text,s); + linepos=0; + picture_len=-1; + } + last_skip=step; + } + + +static int insert_end_line_and_save(int p,int ys) + { + int size; + while (read_buff[buff_pos]==' ' && buff_pos0) picture_len-=ys; + if (picture_len<=0 && total_width!=XMAX) + { + picture_len=0; + total_width=XMAX; + left_skip=0; + } + return p; + } + +static int insert_left_skip(int p,int skip) + { + skip+=left_skip; + if (skip) + { + write_buff[p++]=27; + write_buff[p++]=SPACE; + p=insert_num(write_buff,p,skip); + } + return p; + } + +static void save_line_oboustrane() + { + char space[]=" "; + int xs,ys,ss,mez,mm=0,mc=0; + int i,p; + + for(i=0,xs=0,mez=0,ys=0;iys) ys=p; + } + } + ss=total_width-xs; + p=0; + if (!ys) ys=last_skip; + next_line(ys); + p=insert_left_skip(p,0); + for(i=0,mc=0;iys) ys=p; + } + p=0; + if (!ys) ys=last_skip; + next_line(ys); + ss=total_width-xs; + p=insert_left_skip(p,ss/2); + memcpy(write_buff+p,read_buff,buff_pos); + p+=buff_pos; + write_buff[p]=0; + insert_end_line_and_save(p,ys); + } + +static void save_line_left() + { + int p,z; + int ys; + + p=0; + p=insert_left_skip(p,0);z=p; + if (buff_pos) memcpy(write_buff+p,read_buff,buff_pos); + p+=buff_pos; + write_buff[p]=0; + ys=text_height(write_buff+z); + if (!ys) ys=last_skip; + next_line(ys); + insert_end_line_and_save(p,ys); + } + + +static void save_buffer() + { + while (buff_end>buff_pos && read_buff[buff_end]==32) buff_end--; + if (center) save_line_center(); + else if (buff_pos==buff_end || !distend) save_line_left(); else save_line_oboustrane(); + } + +static void break_line() + { + buff_pos=buff_end; + save_buffer(); + } + +static char read_set(FILE *txt,char *var,char *set) + { + int c; + char *cc; + + fscanf(txt,"%[^=]%c",var,&c); + do + c=fgetc(txt); + while (c<33); + if (c=='"') fscanf(txt,"%[^\"]%c%c",set,&c,&c); + else if (c=='\'') fscanf(txt,"%[^']%c%c",set,&c,&c); + else + { + ungetc(c,txt); + fscanf(txt,"%[^> ]%c",set,&c); + } + while(c<33 && c!=EOF) c=fgetc(txt); + if (c!='>') ungetc(c,txt); + cc=strchr(var,0); + while (cc!=var) + { + cc--; + if (*cc>32) + { + cc++; + break; + } + } + *cc=0; + strupr(set); + strupr(var); + return c; + } + +static int get_data_handle(char *filename,void *dec) + { + int i; + + i=find_handle(filename,dec); + if (i==-1) + { + i=end_ptr++; + def_handle(i,filename,dec,SR_DIALOGS); + } + return i; + } + +static void insert_picture(char *filename,int align,int line,int lsize) + { + int x, y; + short *psiz; + char *c=write_buff; + + psiz=ablock(get_data_handle(filename,pcx_8bit_decomp)); + switch (align) + { + case ANUM_CENTER: + x=(XMAX-psiz[0])/2; + y=linepos; + linepos+=psiz[1]; + *c++=27; + *c++=END_LINE; + c+=insert_num(c,0,psiz[1]+last_skip); + break; + case ANUM_LEFT: x=0; + y=linepos; + left_skip=psiz[0]+5; + total_width=XMAX-left_skip; + break; + case ANUM_RIGHT: total_width=(x=XMAX-psiz[0])-5; + left_skip=0; + y=linepos; + break; + } + if (!lsize) lsize=psiz[1]-line; + picture_len=lsize; + *c++=27; + *c++=PICTURE; + while (*filename) *c++=*filename++; + *c++=':'; + c+=insert_num(c,0,x); + c+=insert_num(c,0,y); + c+=insert_num(c,0,line); + c+=insert_num(c,0,lsize); + *c++=0; + str_add(&all_text,write_buff); + } + +static char read_tag(FILE *txt) + { + char c,var[256],set[256]; + int i; + + i=fscanf(txt,"%[^> ] %c",var,&c); + while(c<33 && i!=EOF) c=i=fgetc(txt); + if (c!='>') ungetc(c,txt); + strupr(var); + if (!strcmp(var,PARAGRAPH)) + { + break_line(); + break_line(); + return 1; + } + if (!strcmp(var,BREAKLINE)) + { + break_line(); + return 1; + } + if (!strcmp(var,IMAGE)) + { + char pic_name[50]=" "; + char alig=0; + int line=0,lsize=0; + + while (c!='>') + { + c=read_set(txt,var,set); + if (!strcmp(var,SRC)) strncpy(pic_name,set,49); + else if (!strcmp(var,ALIGN)) + { + if (!strcmp(set,ALEFT)) alig=1; + else if (!strcmp(set,ARIGHT)) alig=2; + else if (!strcmp(set,ACENTER)) alig=0; + } + else if (!strcmp(var,PIC_LINE)) sscanf(set,"%d",&line); + else if (!strcmp(var,PIC_LSIZ)) sscanf(set,"%d",&lsize); + } + if (pic_name[0]!=0) + insert_picture(pic_name,alig,line,lsize); + return 0; + } + if (!strcmp(var,CENTER1)) center++; + else if (!strcmp(var,CENTER2)) + { + if (center>0) center--; + } + else if (!strcmp(var,DISTEND1)) distend++; + else if (!strcmp(var,DISTEND2)) + { + if (distend>0) distend--; + } + return 0; + } + + +static char skip_section(FILE *txt) + { + int c; + char end=1; + + c=fgetc(txt); + while (c!=']' && c!=EOF) + { + c=fgetc(txt); + end=0; + } + if (c==EOF) end=1; + return end; + } + +void prekodovat(char *c) + { + while (*c) + { + if (*c>137) *c=xlat_table[*c-138]; + c++; + } + } + +static void read_text(FILE *txt) + { + int i; + int xs; + char ss[2]=" "; + char wsp=1; + + buff_pos=0; + buff_end=0; + xs=0; + do + { + i=fgetc(txt); + if (i==EOF) break; + if (i<32) i=32; + if (i=='<') + { + if (read_tag(txt)) + { + xs=0; + wsp=1; + } + continue; + } + if (i=='[') + { + if (skip_section(txt)) break; + continue; + } + if (i==32) + { + if (wsp) continue; + buff_pos=buff_end; + wsp=1; + } + else wsp=0; + if (i=='&') i=fgetc(txt); + if (winconv && i>137) i=xlat_table[i-138]; + ss[0]=i; + xs+=text_width(ss); + read_buff[buff_end++]=i; + if (xs>total_width && !wsp) + { + save_buffer(); + read_buff[buff_end]=0; + xs=text_width(read_buff); + } + } + while (1); + } + +void seek_section(FILE *txt,int sect_number) + { + int c=0,i; + + winconv=0; + do + { + while (c!='[' && c!=EOF) c=fgetc(txt); + if (c=='[') + { + i=-2; + fscanf(txt,"%d",&i); + if (i==sect_number) + { + c=fgetc(txt); + while(c!=']') + { + if (c=='W' || c=='w') winconv=1; + if (c=='K' || c=='k') winconv=0; + c=fgetc(txt); + } + return; + } + } + c=0; + } + while (i!=EOF); + closemode(); + { + char buff[256]; + sprintf(buff,"Nemohu najit odstavec s cislem %d.",sect_number); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONSTOP); + } + exit(1); + } + +void add_text_to_book(char *filename,int odst) + { + FILE *txt; + ENCFILE fl; + + set_font(H_FKNIHA,NOSHADOW(0)); + if (all_text==NULL) all_text=create_list(256); + txt=enc_open(filename,&fl); + if (txt==NULL) return; + seek_section(txt,odst); + read_text(txt); + next_line(1000); + enc_close(&fl); + } + +static char *displ_picture(char *c) + { + char *d; + int x,y,hn,z,ln,sl; + short *sh; + + d=write_buff; + while (*c!=':') *d++=*c++; + *d++=0;c++; + hn=get_data_handle(write_buff,pcx_8bit_decomp); + x=read_num(c,(z=0,&z));c+=z; + y=read_num(c,(z=0,&z));c+=z; + ln=read_num(c,(z=0,&z));c+=z; + sl=read_num(c,(z=0,&z));c+=z; + sh=ablock(hn); + if (sh[1]+y>YMAX) return c; + y+=YLEFT; + x+=relpos; + put_8bit_clipped(sh,GetScreenAdr()+x+scr_linelen2*y,ln,sh[0],sl); + return c; + } + +void write_book(int page) + { + int i=0,y=0,z,zz,ps,pg; + char *c; + char space[]=" "; + + pg=page; + if (all_text==NULL) return; + set_font(H_FKNIHA,NOSHADOW(0)); + relpos=XLEFT; + zz=str_count(all_text); + if (--page) + for(i=0;izz) break; + c=all_text[i]; + if (c==NULL) break; + if (c[0]==27 && c[1]==END_PAGE) break; + while (*c) + { + z=0; + if (*c==27) + { + c++; + switch (*c++) + { + case SPACE: + rel_position_x(read_num(c,&z)); + c+=z; + break; + case END_LINE: + y+=read_num(c,&z); + position(relpos,YLEFT+y); + c+=z; + break; + case PICTURE: + c=displ_picture(c); + break; + } + } + else + { + space[0]=*c++; + outtext(space); + } + } + i++; + } + while (1); + i++;y=0; + relpos=XRIGHT; + if (ps==0) + { + char s[20]; + sprintf(s,texty[135],pg); + set_aligned_position(XLEFT,YLEFT+YMAX,0,0,s); + outtext(s); + } + if (ps==1) + { + char s[20]; + sprintf(s,texty[136],pg+1); + set_aligned_position(XRIGHT+XMAX,YLEFT+YMAX,2,0,s); + outtext(s); + } + } + } + +int count_pages() + { + int i,cn,z; + char *c; + + if (all_text==NULL) return 0; + z=str_count(all_text); + for(i=0,cn=0;i +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include "engine1.h" +#include "globals.h" + + +#define S_jmeno 128 +#define S_kouzlo 129 +#define S_zivel 131 +#define S_level 133 +#define S_mge 134 +#define S_hpnorm_min 135 +#define S_hpnorm_max 136 +#define S_hpzivl_min 137 +#define S_hpzivl_max 138 +#define S_vlastnost 139 +#define S_vls_kolik 140 +#define S_trvani 141 +#define S_cil 142 +#define S_throw_item 142 +#define S_create_item 143 +#define S_backfire 144 +#define S_povaha 145 +#define S_special 146 +#define S_pvls 147 +#define S_animace 148 +#define S_zvuk 149 +#define S_wait 150 +#define S_set 151 +#define S_reset 152 +#define S_drain_min 153 +#define S_drain_max 154 +#define S_accnum 155 +#define S_kondice 156 +#define S_mana 157 +#define S_create_weapon 158 +#define S_mana_clip 159 +#define S_mana_steal 160 +#define S_rand_min 161 +#define S_rand_max 162 +#define S_location_sector 163 +#define S_location_map 164 +#define S_location_dir 165 +#define S_location_x 166 +#define S_location_y 167 + +#define C_kouzelnik 0 +#define C_postava 1 +#define C_policko 2 +#define C_druzina 2 +#define C_policko_pred 3 +#define C_mrtva_postava 4 +#define C_postava_jinde 5 +#define C_nahodna_postava 6 +#define C_jiny_cil 7 + +#define SP_AUTOMAP4 1 +#define SP_AUTOMAP8 2 +#define SP_AUTOMAP15 3 +#define SP_PRIPOJENI1 4 +#define SP_PRIPOJENI3 5 +#define SP_PRIPOJENIA 6 +#define SP_CHVENI 7 +#define SP_DEFAULT_EFFEKT 8 +#define SP_TRUE_SEEING 9 +#define SP_SCORE 10 +#define SP_HALUCINACE 11 +#define SP_TELEPORT 12 +#define SP_SUMMON 13 +#define SP_HLUBINA1 14 +#define SP_HLUBINA2 15 +#define SP_MANABAT 16 +#define SP_VAHY 17 +#define SP_RYCHLOST 18 +#define SP_VIR 19 +#define SP_DEMON1 20 +#define SP_DEMON2 21 +#define SP_DEMON3 22 +#define SP_VZPLANUTI1 23 +#define SP_VZPLANUTI2 24 +#define SP_VZPLANUTI3 25 +#define SP_PHASEDOOR 26 +#define SP_TELEPORT_SECT 27 +#define SP_OPEN_TELEPORT 28 + +#define SS_invis 1 +#define SS_oko 2 +#define SS_tvar 4 + +#define FLG_TRUESEEING 0x10000 //zapnuty TRUESEEING +#define FLG_HLUBINA1 0x20000 //zapnuta HLUBINA pro vsechny +#define FLG_HLUBINA2 0x40000 //zapnuta HLUBINA pro potvory +#define FLG_SCORE 0x80000 //zapnute ukazovani score nad potvorama. +#define FLG_HALUCINACE 0x100000 // zapne halucinaci + +#define GET_WORD(c) *(word *)c;c+=2 + +#define MAX_SPELLS 500 + +char running_anm=0; + +char hlubina_level=0; + +word *anim_render_buffer; + +short teleport_target=0; //cil teleportace + +typedef struct tteleportlocation +{ + short loc_x; + short loc_y; + const char *map; + word sector; + word dir; +}TTELEPLOCATION; + +static TTELEPLOCATION TelepLocation; + +typedef struct tkouzlo + { + word num,um,mge; + word pc; + short owner,accnum; //accnum = akumulacni cislo, owner = kdo kouzlo seslal + int start; + short cil; //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) + char povaha; + word backfire; //backfire / 1 = demon , 0 = bez demona + word wait; //wait - cekani pocet animaci + word delay; //delay - cekani pocet kol + char traceon; //jinak noanim - neprehravaji se animace a zvuky + char spellname[28]; + word teleport_target; + }TKOUZLO; + +TKOUZLO *spell_table[MAX_SPELLS]; +short *vls_table[MAX_SPELLS]; //nove vlastnosti postav + //pokud je cislo vetsi nez 0x7f00 pak dolni byte uvadi percentualni pomer +static long _flag_map[MAX_SPELLS]; //tabulka nastavenych priznaku pro kouzlo. + //prvnich 16 bitu je pro postavu + //hornich 16 bitu je globalne + +short parm1,parm2; +char twins; + +static short rand_value; + +static word *paleta; + +void show_full_lfb12e(void *target,void *buff,void *paleta); +//#pragma aux show_full_lfb12e parm[edi][esi][ebx] modify [eax ecx] +void show_delta_lfb12e(void *target,void *buff,void *paleta); +//#pragma aux show_delta_lfb12e parm[edi][esi][ebx] modify [eax ecx] +char mob_check_next_sector(int sect,int dir,char alone,char passable); + +void call_spell(int i); +int calculatePhaseDoor(int sector, int dir, int um); + + +static void animace_kouzla(int act,void *data, int ssize) + { + switch (act) + { + case MGIF_LZW: + case MGIF_COPY:show_full_lfb12e(anim_render_buffer,data,paleta);break; + case MGIF_DELTA:show_delta_lfb12e(anim_render_buffer,data,paleta);break; + case MGIF_PAL:paleta=data;*paleta|=0x8000;break; + } + } + + + +static void play_anim(va_list args) //tasked animation +//#pragma aux play_anim parm [] + { + int block=va_arg(args,int); +#define ANIM_SIZE (320*180*2) + void *anm; + long *l,c; + + if (running_anm) + { + SEND_LOG("(ERROR)(ANIM) Animation's mutex is already in use!",0,0); + return; + } + SEND_LOG("(ANIM) Running animation number %xh",block,0); + anim_render_buffer=getmem(ANIM_SIZE); + mgif_install_proc(animace_kouzla); + running_anm=1; + l=(void *)anim_render_buffer; + c=ANIM_SIZE/4;do *l++=0x80008000; while (--c); + alock(block); + anm=open_mgif(ablock(block)); + c=0; + SEND_LOG("(ANIM) Buffer is now ready...",0,0); + while (anm!=NULL) + { + task_wait_event(E_KOUZLO_ANM); + c++; + SEND_LOG("(ANIM) Rendering frame %d in animation %xh",c,block); + anm=mgif_play(anm); + neco_v_pohybu=1; + } + task_wait_event(E_KOUZLO_ANM); + close_mgif(); + running_anm=0; + free(anim_render_buffer); + SEND_LOG("(ANIM) Closing animation %xh",block,0); + aunlock(block); + } + +void play_big_mgif_animation(int block) + { + add_task(2048,play_anim,block); + task_sleep(NULL); + } + +int get_spell_mana(int num) + { + TKOUZLO *p; + + p=(TKOUZLO *)ablock(H_KOUZLA); + return p[num].mge; + } + +int get_spell_um(int num) + { + TKOUZLO *p; + + p=(TKOUZLO *)ablock(H_KOUZLA); + return p[num].um; + } + + +int get_spell_used(int num) + { + TKOUZLO *p; + + p=(TKOUZLO *)ablock(H_KOUZLA); + return (p[num].start!=0); + } + +char get_spell_track(int num) + { + TKOUZLO *p; + + p=(TKOUZLO *)ablock(H_KOUZLA); + return (p[num].traceon & 1); + } + +char get_spell_teleport(int num) + { + TKOUZLO *p; + + p=(TKOUZLO *)ablock(H_KOUZLA); + return (p[num].traceon & 2); + } + + +int get_spell_color(THUMAN *p,int num) + { + TKOUZLO *z; + + z=(TKOUZLO *)ablock(H_KOUZLA); + z+=num; + if (!z->start) return 1; + if (z->mge>p->mana) return 1; + if (z->um<=p->vlastnosti[VLS_SMAGIE]) return 0; + if (z->um<=(p->vlastnosti[VLS_SMAGIE]*2)) return 2; + return 1; + } + +char get_rune_enable(THUMAN *p,int strnum) + { + int i; + for(i=0;i<3;i++) if (get_spell_color(p,strnum+i)!=1) return 1; + return 0; + } + +char *get_rune_name(int strnum) + { + TKOUZLO *z; + z=(TKOUZLO *)ablock(H_KOUZLA); + z+=strnum; + return z->spellname; + } + +void spell_anim(char *name) + { + int i; + i=find_handle(name,NULL); + if (i==-1) i=end_ptr++; + def_handle(i,name,NULL,SR_ITEMS); + add_task(8196,play_anim,i); + } + +void spell_sound(char *name) + { + int i; + i=find_handle(name,wav_load); + if (i==-1) i=end_ptr++; + def_handle(i,name,wav_load,SR_ZVUKY); + play_sample_at_channel(i,0,100); + } + +void get_sector_dir(int cil,word *sector,char *dir) + { + if (cil>0) + { + cil--; + if (postavy[cil].used) *sector=postavy[cil].sektor,*dir=postavy[cil].direction; + } + else if (cil<0) + { + cil=-cil-1; + *sector=mobs[cil].sector; + *dir=mobs[cil].dir; + } + } + +static void spell_vzplanuti3(int ss,int hit,int zivel) + { + if (map_coord[ss].flags & MC_PLAYER) + { + THUMAN *h;int i; + + for(i=0,h=postavy;iused && h->lives && h->sektor==ss) + { + int ochrana=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); + player_hit(h,hit*ochrana/100,1); + } + } + if (mob_map[ss]) + { + int i=mob_map[ss]; + while(i) + { + TMOB *m=mobs+i-1; + int ochrana=mgochrana(m->vlastnosti[VLS_OHEN+zivel]); + vybrana_zbran=-1; + mob_hit(m,hit*ochrana/100); + i=m->next; + } + } + + } + +static void spell_vzplanuti2(THE_TIMER *tt) + { + int ss,ss1,ss2,i,dp,dl,du; + int zivel; + + i=tt->userdata[2];if (i<1) i++; + du=tt->userdata[1] & 0xff; + ss=tt->userdata[0]; + zivel=tt->userdata[1] >> 8; + if (map_sides[(ss<<2)+du].flags & SD_PLAY_IMPS) return; + ss1=ss2=ss=map_sectors[ss].step_next[du]; + if (ss==0) return; + dp=du+1&3; + dl=du+3&3; + do + { + if (ss1!=0) + { + add_spectxtr(ss1,H_ARMAGED,H_ARMA_CNT,1,0); + spell_vzplanuti3(ss1,tt->userdata[3],zivel); + } + if (ss2!=ss1 && ss2!=0) + { + add_spectxtr(ss2,H_ARMAGED,H_ARMA_CNT,1,0); + spell_vzplanuti3(ss2,tt->userdata[3],zivel); + } + if (~map_sides[(ss1<<2)+dp].flags & SD_PLAY_IMPS) ss1=map_sectors[ss1].step_next[dp]; + if (~map_sides[(ss2<<2)+dl].flags & SD_PLAY_IMPS) ss2=map_sectors[ss2].step_next[dl]; + } + while(--i); + if (tt->userdata[2]) tt->userdata[2]++; + //tt->userdata[3]=tt->userdata[3]*2/3; + tt->userdata[0]=ss; + } + +static void spell_vzplanuti(int cil,int count,int hit,char mode,char zivel) + { + THE_TIMER *tt; + int sector,smer; + int i,o,d; + if (cil<0) + { + TMOB *m=&mobs[-cil-1]; + sector=m->sector; + smer=m->dir; + } + else if (cil>0) + { + THUMAN *h=postavy+cil-1; + sector=h->sektor; + smer=h->direction; + } + if (mode) {o=smer;d=smer+1;}else o=0,d=4; + for(i=o;i1) tt=add_to_timer(TM_VZPLANUTI,25,count-1,spell_vzplanuti2); + else tt=&tts; + tt->userdata[0]=sector; + tt->userdata[1]=i+(zivel<<8); + tt->userdata[2]=!mode; + tt->userdata[3]=hit; + spell_vzplanuti2(tt); + } + neco_v_pohybu=1; + } + +void spell_create(int cil,int what) + { + word sector=0; + char dir; + short p[2]; + + get_sector_dir(cil,§or,&dir); + p[0]=what+1; p[1]=0; + push_item(sector,dir,p); + } + +void spell_create_weapon(int cil,int what) + { + THUMAN *h=postavy+cil-1; + short lr,pr; + + lr=h->wearing[PO_RUKA_L]; + pr=h->wearing[PO_RUKA_R]; + if (lr && glob_items[lr-1].umisteni==PL_OBOUR) pr=lr; + else if (pr && glob_items[pr-1].umisteni==PL_OBOUR) lr=pr; + if (lr && pr) + { + char s[256]; + + sprintf(s,texty[86],h->jmeno); + bott_disp_text(s); + return; + } + if (!pr) h->wearing[PO_RUKA_R]=what+1; + else if (!lr) h->wearing[PO_RUKA_L]=what+1; + prepocitat_postavu(h); + } + +void spell_throw(int cil,int what) + { + word sector=0; + char dir; + LETICI_VEC *fly; + + get_sector_dir(cil,§or,&dir); + fly=create_fly(); + fly->item=what+1; + fly->items=NULL; + fly->xpos=-63; + fly->ypos=0; + fly->zpos=80; + fly->speed=32; + fly->velocity=0; + fly->flags=FLY_NEHMOTNA | FLY_DESTROY; + fly->sector=sector; + fly->smer=dir; + fly->owner=cil; + fly->hit_bonus=0; + fly->damage=0; + fly->lives=glob_items[what].user_value; + fly->counter = 0; + add_fly(fly); + } + + +void zmen_vlastnost(int num,int cil,int what,int how) + { + if (!how) return; + if (cil<0) + { + cil=-cil-1; + if (mobs[cil].vlastnosti[what]+how<0) how=-mobs[cil].vlastnosti[what]; + vls_table[num][what]-=how; + mobs[cil].vlastnosti[what]+=how; + } + else if(cil>0) + { + THUMAN *p; + + vls_table[num][what]-=how; + cil--; + p=&postavy[cil]; + postavy[cil].stare_vls[what]+=how; + prepocitat_postavu(&postavy[cil]); + if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; + //if (p->mana>p->vlastnosti[VLS_MAXMANA]) p->lives=p->vlastnosti[VLS_MAXMANA]; + if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->lives=p->vlastnosti[VLS_KONDIC]; + } + } + +void zmen_vlastnost_percent(int num,int cil,int what,int how) + { + int x; + int c; + if (cil<0) + { + c=-cil-1; + x=mobs[c].vlastnosti[what]; + } + else + { + c=cil-1; + x=postavy[c].vlastnosti[what]; + } + x=x*abs(how)/100;if (how<0) x=-x; + zmen_vlastnost(num,cil,what,x); + } + +char hod_na_uspech(int cil,TKOUZLO *k) + { + if (!k->povaha) return 1; + if (cil) + { + int z,zv; + short *p; + + if (cil<0) + { + cil=-cil-1; + p=mobs[cil].vlastnosti+VLS_OHEN; + } + else if(cil>0) + { + cil--; + p=postavy[cil].vlastnosti+VLS_OHEN; + } + zv=mgochrana(p[k->pc]); + z=rnd(100); + return (z<=zv); + } + return 0; + } + +void spell_end_global() + { + long l=0; + int i; + for(i=0;isektor=q->sektor; + p->direction=q->direction; + p->groupnum=q->groupnum; + p->demon_save=q; + } + +static void zmena_z_demona(int hrac) + { + THUMAN *q=postavy+hrac; + THUMAN *p=q->demon_save; + + p->sektor=q->sektor; + p->direction=q->direction; + p->groupnum=q->groupnum; + *q=*p; + free(p); + } + +static void zmena_demona(int hrac,int demon,char smer) + { + THUMAN *p=postavy+hrac; + + if (postavy[hrac].stare_vls[VLS_KOUZLA] & SPL_DEMON && smer!=0) return; + if (~postavy[hrac].stare_vls[VLS_KOUZLA] & SPL_DEMON && smer==0) return; + if (smer!=0) zmena_na_demona(hrac,demon);else zmena_z_demona(hrac); + if (smer!=0) + { + p->lives=p->vlastnosti[VLS_MAXHIT]; + p->kondice=p->vlastnosti[VLS_KONDIC]; + p->mana=p->vlastnosti[VLS_MAXMANA]; + p->jidlo=MAX_HLAD(p); + p->voda=MAX_ZIZEN(p); + } + reg_grafiku_postav(); + } + +static void unaffect_after_demon(int cil) + { + int i; + char a; + TKOUZLO *spl; + + SEND_LOG("(SPELLS) Unaffecting after demon...",0,0); + do + { + a=0; + for(i=0;spl=spell_table[i],icil==cil && spl->backfire==1) + { + if (spl->wait) + { + spl->wait=0;call_spell(i); + a=1; + } + if (spl->cil>0) + { + spl->delay=0;call_spell(i); + a=1; + } + } + } + while(a); + } + +void spell_end(int num,int ccil,int owner) + { + int i,l; + int cil=ccil; + for(i=0;i0) + { + cil--; + if (_flag_map[num] & SPL_DEMON) + { + unaffect_after_demon(ccil); + zmena_demona(cil,owner,0); + _flag_map[num]&=~SPL_DEMON; + SEND_LOG("(SPELLS) Spell 'Demon' has ended...",0,0); + } + postavy[cil].stare_vls[VLS_KOUZLA]&=~_flag_map[num]; + if (cil>=0 && cilcil==ccil && ccil>0 && spell_table[i]->owner>=0) + { + postavy[cil].spell=1; + bott_draw(0); + break; + }; + l=_flag_map[num]; + _flag_map[num]=0; + if (l>0xffff) spell_end_global(); + SEND_LOG("(SPELLS) Spell ID %d ends.",num,0); + } + +static void spell_demon(int num,TKOUZLO *spl,int cil,int demon) + { + cil--; + if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON) return; + spl->owner=demon; + zmena_demona(cil,demon,1); + postavy[cil].stare_vls[VLS_KOUZLA]|=SPL_DEMON; + _flag_map[num]|=SPL_DEMON; + bott_draw(1); + } + +void spell_hit(int cil,int min,int max,int owner) + { + if (cil) + if (cil<0) + { + TMOB *m; + cil=-cil-1; + m=&mobs[cil]; + select_player=owner; + vybrana_zbran=-1; + mob_hit(m,min+rnd(max-min)); + } + else if(cil>0) + { + THUMAN *h; + int vysl; + + cil--; + h=&postavy[cil]; + vysl=min+rnd(max-min); + if (vysl<0) + { + h->lives-=vysl,h->lives=min(h->lives,h->vlastnosti[VLS_MAXHIT]); + if (h->groupnum==0) h->groupnum=cur_group; + } + else player_hit(h,vysl,1); + + bott_draw(0); + } + } + +void spell_hit_zivel(int cil,int min,int max,int owner,int zivel) + { + int ochrana; + if (cil) + if (cil<0) + { + TMOB *m; + cil=-cil-1; + m=&mobs[cil]; + select_player=owner; + ochrana=mgochrana(m->vlastnosti[VLS_OHEN+zivel]); + vybrana_zbran=-1; + mob_hit(m,(min+rnd(max-min))*ochrana/100); + } + else if(cil>0) + { + THUMAN *h; + + cil--; + h=&postavy[cil]; + ochrana=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); + player_hit(h,(min+rnd(max-min))*ochrana/100,0); + bott_draw(0); + } + } + + +void set_flag(int num,int cil,int flag,int what) + { + if (cil>0) + { + cil--; + if (what) + { + postavy[cil].stare_vls[VLS_KOUZLA]|=flag; + _flag_map[num]|=flag; + } + else + { + postavy[cil].stare_vls[VLS_KOUZLA]&=~flag; + _flag_map[num]&=~flag; + } + zneplatnit_block(cil+H_CHARS); + prepocitat_postavu(postavy+cil); + } + if (cil<0) + { + cil=-cil-1; + if (what) + { + mobs[cil].vlastnosti[VLS_KOUZLA]|=flag; + _flag_map[num]|=flag; + } + else + { + mobs[cil].vlastnosti[VLS_KOUZLA]&=~flag; + _flag_map[num]&=~flag; + } + } + } + +void spell_automap(int kolik,int cil) + { + int x1,y1; + int xx,yy; + int i,layer; + THUMAN *p; + + if (cil<=0) return; + cil--; + p=&postavy[cil]; + x1=map_coord[p->sektor].x; + y1=map_coord[p->sektor].y; + layer=map_coord[p->sektor].layer; + for(i=1;isektor; + if (map_coord[from_sect].flags & MC_NOSUMMON) + { + char *s; + + s=(char *)alloca(strlen(texty[87])+30); + sprintf(s,texty[87],p->jmeno); + bott_disp_text(s); + return; + } + p->sektor=postavy[owner].sektor; + kolik--; + for(i=0;igroupnum && postavy[i].sektor==from_sect) + { + postavy[i].sektor=viewsector; + kolik--; + } + for(i=0;isektor=viewsector; + kolik--; + } + add_spectxtr(viewsector,H_TELEP_PCX,14,1,0); + auto_group(); + for(i=0;ijmeno); + bott_disp_text(s); + } + bott_draw(0); + build_player_map(); + } + +void spell_teleport(int cil,int owner, int teleport_target) + { + if (teleport_target==-1) + { + int sektor; + int dir; + int um; + + if (cil>0) {sektor=postavy[cil-1].sektor;dir=postavy[cil-1].direction;} + else if (cil<0) {sektor=mobs[-cil-1].sector;dir=mobs[-cil-1].dir;} + if (owner>=0) um=postavy[owner].vlastnosti[VLS_SMAGIE]; + teleport_target=calculatePhaseDoor(sektor,dir,um); + } + if (map_coord[teleport_target].flags & MC_NOSUMMON) + { + if (owner>=0) bott_disp_text(texty[88]); + return; + } + if (cil>0) + { + if (mob_map[teleport_target]) + { + if (owner>=0) bott_disp_text(texty[85]); + return; + } + destroy_player_map(); + cil--; + postavy_teleport_effect(teleport_target,postavy[cil].direction,1<=0) + zmen_skupinu(postavy+owner); + } + else if (cil<0) + { + if (map_coord[teleport_target].flags & MC_PLAYER) + { + if (owner>=0) bott_disp_text(texty[85]); + return; + } + cil=-cil-1; + play_sample_at_sector(H_SND_TELEPOUT,viewsector,mobs[cil].sector,0,0); + add_spectxtr(mobs[cil].sector,H_TELEP_PCX,14,1,0); + mobs[cil].sector=teleport_target; + play_sample_at_sector(H_SND_TELEPOUT,viewsector,teleport_target,0,0); + add_spectxtr(teleport_target,H_TELEP_PCX,14,1,0); + mobs[cil].next=0; + refresh_mob_map(); + } + //schovej_mysku(); + } + +void spell_teleport_sector(int cil,int owner) +{ + if (cil<0) + { + if (owner>=0) bott_disp_text(texty[85]); + return; + } + if (cil>0) + { + cil--; + if (TelepLocation.map) + { + destroy_player_map(); + if (stricmp(TelepLocation.map,level_fname)!=0) + { + int sector=postavy[cil].sektor; + int i; + + if (cil!=owner) return; + postavy_teleport_effect(0,0,0,1); + strncpy(loadlevel.name,TelepLocation.map,12); + loadlevel.name[12]=0; + loadlevel.start_pos=TelepLocation.sector; + loadlevel.dir=TelepLocation.dir; + send_message(E_CLOSE_MAP); + save_map=1; + + for(i=0;i=0) + zmen_skupinu(postavy+owner); + } + } + else + { + int sector=postavy[cil].sektor; + int dir=postavy[cil].direction; + int x=map_coord[sector].x; + int y=map_coord[sector].y; + int stpx=0,stpy=0,diffx=0,diffy=0; + switch (dir) + { + case 0: stpy=-1;diffx=1;break; + case 1: stpx=1;diffy=1;break; + case 2: stpy=1;diffx=-1;break; + case 3: stpx=-1;diffy=-1;break; + }; + { + int newx=x+TelepLocation.loc_x*stpx+TelepLocation.loc_y*diffx; + int newy=y+TelepLocation.loc_x*stpx+TelepLocation.loc_y*diffy; + int i; + int dist; + int nearest=0; + int nearestdst=0x7FFFFFFF; + + for (i=1;i=0) bott_disp_text(texty[88]); + return; + } + destroy_player_map(); + postavy_teleport_effect(sector,postavy[cil].direction,1<=0) + zmen_skupinu(postavy+owner); + } + } + +} + +static void spell_summon(int cil) + { + short sector,i,rn,rno,slc; + char stdir,p; + + if (cil>0) sector=postavy[cil-1].sektor; + if (cil<0) sector=mobs[-cil-1].sector; + for(i=0;ivlajky & MOB_LIVE && ~m->vlajky & MOB_RELOAD) break; + } + if (i==MAX_MOBS) return; + slc=i; + rno=rn=rnd(256)+1; + do + { + for(i=0;istay_strategy & (MOB_WATCH|MOB_WALK)) == (MOB_WATCH|MOB_WALK) && + (m->vlajky & MOB_LIVE) && (~m->vlajky & MOB_PASSABLE) && (~m->vlajky & MOB_MOBILE)) + { + rn--;if (!rn) break; + } + } + } + while (i==MAX_MOBS && rn!=rno); + if (i==MAX_MOBS) return; + memcpy(mobs+slc,mobs+i,sizeof(TMOB)); + p=map_coord[sector].flags & MC_PLAYER; + if (!p) + { + int m; + m=mob_map[sector]-1; + p=mobs[m].stay_strategy & MOB_BIG || mobs[m].next; + } + if (p) + { + int i; + stdir=rnd(4); + + for(i=0;i<4;i++,stdir=stdir+1&3) + if (!mob_check_next_sector(sector,stdir,mobs[slc].stay_strategy,0)) break; + if (i==4) + { + mobs[slc].vlajky&=~MOB_LIVE; + return; + } + sector=map_sectors[sector].step_next[stdir]; + } + mobs[slc].sector=sector; + if (cil>0) mobs[slc].dir=postavy[cil-1].direction+2&3; + if (cil<0) mobs[slc].dir=mobs[-cil-1].dir; + refresh_mob_map(); + } + +static void spell_manabat(int cil) + { + if (cil>0) + { + cil--; + if (postavy[cil].mana_battery>postavy[cil].mana) postavy[cil].mana_battery=postavy[cil].mana; + else postavy[cil].mana=postavy[cil].mana_battery; + } + } + +static void spell_vahy_osudu(int zivel,char povaha) + { + int i; + int min; + THUMAN *h; + TMOB *m; + + min=32767; + for(i=0,h=postavy;iused && h->lives && min>h->lives) min=h->lives; + for(i=0,m=mobs;ivlajky & MOB_LIVE && m->vlajky & MOB_IN_BATTLE && m->liveslives; + for(i=0,h=postavy;iused && h->lives) + { + int obr=mgochrana(h->vlastnosti[VLS_OHEN+zivel]); + if (!povaha || rnd(100)<=obr) + { + h->lives=min; + display_spell_in_icone(H_SPELLDEF,1<vlajky & MOB_LIVE && m->vlajky & MOB_IN_BATTLE && m->livesvlastnosti[VLS_OHEN+zivel]); + if (!povaha || rnd(100)<=obr) + m->lives=min; + } + bott_draw(1); + } + +static void spell_open_teleport(int cil, int owner) +{ + int sector; + int dir; + if (cil<0) {sector=mobs[-cil-1].sector;dir=mobs[-cil-1].dir;} + else if (cil>0) {sector=postavy[cil-1].sektor;dir=postavy[cil-1].direction;} + else return; + + if (map_sectors[sector].step_next[dir] && (~map_sides[sector*4+dir].flags & SD_THING_IMPS)) + sector=map_sectors[sector].step_next[dir]; + + if (map_coord[sector].flags & MC_NOSUMMON) + { + if (owner>=0) bott_disp_text(texty[88]); + return; + } + + if (mob_map[sector]) + { + if (owner>=0) bott_disp_text(texty[85]); + return; + } + + + if (map_sectors[sector].sector_type>=S_USERTELEPORT && + map_sectors[sector].sector_type<=S_USERTELEPORT_END) + { + int i; + int otherside; + map_sectors[sector].sector_type-=S_USERTELEPORT ; + otherside=map_sectors[sector].sector_tag; + for (i=0;i<4;i++) {map_sides[sector*4+i].flags&=~SD_SEC_VIS;map_sides[sector*4+i].sec_anim=0;map_sides[sector*4+i].sec=0;} + map_sectors[sector].sector_tag=0; + add_spectxtr(sector,H_TELEP_PCX,14,1,0); + play_sample_at_sector(H_SND_TELEPOUT,viewsector,sector,0,0); + if (otherside!=sector && otherside) + { + map_sectors[otherside].sector_type-=S_USERTELEPORT ; + for (i=0;i<4;i++) {map_sides[otherside*4+i].flags&=~SD_SEC_VIS;map_sides[otherside*4+i].sec_anim=0;map_sides[otherside*4+i].sec=0;} + map_sectors[otherside].sector_tag=0; + add_spectxtr(otherside,H_TELEP_PCX,14,1,0); + play_sample_at_sector(H_SND_TELEPOUT,viewsector,otherside,0,0); + } + } + else + { + int type=map_sectors[sector].sector_type; + int i; + char allowed=1; + if (type!=S_NORMAL && (type=S_VODA)) allowed=0; + if (allowed && map_sectors[sector].sector_tag!=0) allowed=0; + if (allowed) + for (i=0;i<4;i++) + if (map_sides[sector*4+i].sec) allowed=0; + if (allowed) + { + TSTENA *st,*stt; + int templateSect=0; + int i,j; + for (i=0;templateSect==0 && i=0) bott_disp_text(texty[85]); + return; + } + map_sectors[sector].sector_type+=S_USERTELEPORT; + st=map_sides+4*sector; + stt=map_sides+4*templateSect; + for (i=0;i<4;i++) + { + st->flags|=SD_SEC_VIS|SD_SEC_ANIM; + st->sec_anim=stt->sec_anim; + st->sec=stt->sec; + st++; + } + for (i=0;i=S_USERTELEPORT && map_sectors[i].sector_type<=S_USERTELEPORT_END) + if (map_sectors[i].sector_tag==i) break; + if (i!=mapsize) + { + map_sectors[sector].sector_tag=i; + map_sectors[sector].side_tag=map_sectors[i].side_tag; + map_sectors[i].sector_tag=sector; + map_sectors[i].side_tag=(dir+2)&3; + } + else + { + map_sectors[sector].sector_tag=sector; + map_sectors[sector].side_tag=(dir+2)&3; + } + add_spectxtr(sector,H_TELEP_PCX,14,1,0); + play_sample_at_sector(H_SND_TELEPOUT,viewsector,sector,0,0); + } + else + if (owner>=0) bott_disp_text(texty[85]); + } +} + +static void spell_rychlost(int num,int cil) + { + short *c; + if (cil>0) c=postavy[cil-1].vlastnosti; + else c=mobs[-cil-1].vlastnosti; + if (c[VLS_POHYB]<15) zmen_vlastnost(num,cil,VLS_POHYB,15-c[VLS_POHYB]); + } + +void spell_special(int num,TKOUZLO *spl,int spc) + { + switch (spc) + { + case SP_AUTOMAP4:spell_automap(4,spl->cil);break; + case SP_AUTOMAP8:spell_automap(8,spl->cil);break; + case SP_AUTOMAP15:spell_automap(15,spl->cil);break; + case SP_PRIPOJENI1:spell_pripojeni(1,spl->cil,spl->owner);break; + case SP_PRIPOJENI3:spell_pripojeni(3,spl->cil,spl->owner);break; + case SP_PRIPOJENIA:spell_pripojenia(spl->owner);break; + case SP_CHVENI:chveni(100);break; + case SP_DEFAULT_EFFEKT: + if (spl->cil>0)display_spell_in_icone(H_SPELLDEF,1<<(spl->cil-1));break; + case SP_TRUE_SEEING: true_seeing=1;_flag_map[num]|=FLG_TRUESEEING;break; + case SP_SCORE:show_lives=1;_flag_map[num]|=FLG_SCORE;break; + case SP_HALUCINACE:set_halucination=1;_flag_map[num]|=FLG_HALUCINACE; + hal_sector=rnd(mapsize-1)+1;hal_dir=rnd(4); + break; + case SP_TELEPORT:if (hod_na_uspech(spl->cil,spl)) spell_teleport(spl->cil,spl->owner,spl->teleport_target);break; + case SP_PHASEDOOR:if (hod_na_uspech(spl->cil,spl)) spell_teleport(spl->cil,spl->owner,-1);break; + case SP_SUMMON: spell_summon(spl->cil); + case SP_HLUBINA1:if (hlubina_level==0) hlubina_level=1;_flag_map[num]|=FLG_HLUBINA1; + break; + case SP_HLUBINA2:hlubina_level=2;_flag_map[num]|=FLG_HLUBINA2; + break; + case SP_MANABAT:spell_manabat(spl->cil); + break; + case SP_VAHY:spell_vahy_osudu(spl->pc,spl->povaha);break; + case SP_RYCHLOST:spell_rychlost(num,spl->cil);break; + case SP_DEMON1:spell_demon(num,spl,spl->cil,0);break; + case SP_DEMON2:spell_demon(num,spl,spl->cil,1);break; + case SP_DEMON3:spell_demon(num,spl,spl->cil,2);break; + case SP_VZPLANUTI1:spell_vzplanuti(spl->cil,1,rand_value,1,spl->pc);break; + case SP_VZPLANUTI2:spell_vzplanuti(spl->cil,5,rand_value,1,spl->pc);break; + case SP_VZPLANUTI3:spell_vzplanuti(spl->cil,5,rand_value,0,spl->pc);break; + case SP_TELEPORT_SECT: if (hod_na_uspech(spl->cil,spl)) spell_teleport_sector(spl->cil,spl->owner);break; + case SP_OPEN_TELEPORT: spell_open_teleport(spl->cil,spl->owner);break; + } + } + +void spell_drain(TKOUZLO *p,int cil,int min,int max) + { + int drw; + int sect,dir; + + drw=min+rnd(max-min); + if (cil>0) + { + cil--; + sect=postavy[cil].sektor; + dir=postavy[cil].direction; + if (map_sides[(sect<<2)+dir].flags & SD_PLAY_IMPS) + { + postavy[cil].lives-=drw; + player_check_death(&postavy[cil],0); + } + else + { + int chaos;int potvora,ochrana; + TMOB *m; + + potvora=vyber_potvoru(sect,dir,&chaos); + if (potvora==-1) return; + m=mobs+potvora; + ochrana=mgochrana(m->vlastnosti[VLS_OHEN+p->pc]); + drw=ochrana*drw/100; + vybrana_zbran=-1; + mob_hit(m,drw); + battle=1; + postavy[cil].lives+=drw/4; + if (postavy[cil].lives>postavy[cil].vlastnosti[VLS_MAXHIT]) + postavy[cil].lives=postavy[cil].vlastnosti[VLS_MAXHIT]; + } + } + } + +static void set_kondice_mana(int kolik,TKOUZLO *p,int what,char clip) + { + int cil=p->cil; + if (cil>0) + { + THUMAN *p; + cil--; + p=postavy+cil; + if (what==S_kondice) + { + p->kondice+=kolik; + if (p->kondice<0) p->kondice=0; + if (clip) + if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC]; + } + if (what==S_mana) + { + p->mana+=kolik; + if (p->mana<0) p->mana=0; + if (clip) + if (p->mana>p->vlastnosti[VLS_MAXMANA]) p->mana=p->vlastnosti[VLS_MAXMANA]; + } + } + } + +static void spell_mana_steal(int kolik,int cil,int owner) + { + if (cil>0) + { + THUMAN *h=postavy+cil-1; + h->mana-=h->vlastnosti[VLS_MAXMANA]*kolik/100; + if (h->mana<0) h->mana=0; + } + if (cil<0) + { + if (owner>=0) + { + THUMAN *h=postavy+owner; + if (h->manavlastnosti[VLS_MAXMANA]) h->mana+=h->vlastnosti[VLS_MAXMANA]*kolik/100; + } + } + } + +static void calc_rand_value(int val1,int val2) + { + rand_value=val1+rnd(val2-val1+1); + } + +void call_spell(int i) + { + TKOUZLO *p; + char *c; + int z; + char ext=0; + int cil; + + SEND_LOG("(SPELLS) Calculating spell ID: %d",i,0); + p=spell_table[i]; + if (p==NULL) return; + cil=p->cil; + if (cil>0) + { + cil--; + if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON && ~_flag_map[i] & SPL_DEMON && p->backfire==0) + { + p->wait=1; + return; + } + } + if (p->delay) return; + if (p->wait) return; + c=(char *)ablock(H_KOUZLA); + c+=p->start; + twins=0; + do + switch (twins=twins==3?0:twins,*c++) + { + case S_zivel:p->pc=GET_WORD(c); + if (p->owner>=0 && !GlobEvent(MAGLOB_ONFIREMAGIC+p->pc,postavy[p->owner].sektor,postavy[p->owner].direction)) + { + spell_end(i,p->cil,p->owner); + return; + } + break; + case S_hpnorm_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_hit(p->cil,parm1,parm2,p->owner);break; + case S_hpnorm_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_hit(p->cil,parm1,parm2,p->owner);break; + case S_hpzivl_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_hit_zivel(p->cil,parm1,parm2,p->owner,p->pc);break; + case S_hpzivl_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_hit_zivel(p->cil,parm1,parm2,p->owner,p->pc);break; + case S_vlastnost:parm1=GET_WORD(c);twins|=1; + if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost(i,p->cil,parm1,parm2);break; + case S_vls_kolik:parm2=GET_WORD(c);twins|=2; + if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost(i,p->cil,parm1,parm2);break; + case S_trvani:p->delay=GET_WORD(c);p->wait=0;ext=1;break; + case S_throw_item:z=GET_WORD(c);spell_throw(p->cil,z);break; + case S_create_item:z=GET_WORD(c);spell_create(p->cil,z);break; + case S_create_weapon:z=GET_WORD(c);spell_create_weapon(p->cil,z);break; + case S_animace:if (p->owner>=0 && !p->traceon)spell_anim(c);c=strchr(c,0);c++;break; + case S_zvuk:if (p->owner>=0 && !p->traceon)spell_sound(c);c=strchr(c,0);c++;break; + case S_wait:p->wait=GET_WORD(c);if (p->owner>=0) ext=1;break; + case 0xff:spell_end(i,p->cil,p->owner);return; + case S_pvls:parm2=GET_WORD(c);twins|=2; + if (twins==3) if (hod_na_uspech(p->cil,p)) zmen_vlastnost_percent(i,p->cil,parm1,parm2);break; + case S_set:parm2=GET_WORD(c);if (hod_na_uspech(p->cil,p)) set_flag(i,p->cil,parm2,1);break; + case S_reset:parm2=GET_WORD(c);if (hod_na_uspech(p->cil,p)) set_flag(i,p->cil,parm2,0);break; + case S_special:parm2=GET_WORD(c);spell_special(i,p,parm2);break; + case S_drain_min:parm1=GET_WORD(c);twins|=1;if (twins==3) spell_drain(p,p->cil,parm1,parm2);break; + case S_drain_max:parm2=GET_WORD(c);twins|=2;if (twins==3) spell_drain(p,p->cil,parm1,parm2);break; + case S_rand_min:parm1=GET_WORD(c);twins|=1;if (twins==3) calc_rand_value(parm1,parm2);break; + case S_rand_max:parm2=GET_WORD(c);twins|=2;if (twins==3) calc_rand_value(parm1,parm2);break; + case S_mana:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_mana,0);break; + case S_kondice:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_kondice,1);break; + case S_mana_clip:parm1=GET_WORD(c);set_kondice_mana(parm1,p,S_mana,1);break; + case S_mana_steal:parm1=GET_WORD(c);spell_mana_steal(parm1,p->cil,p->owner);break; + case S_location_sector: parm1=GET_WORD(c); + TelepLocation.sector=parm1; + TelepLocation.loc_x=0; + TelepLocation.loc_y=0; + break; + case S_location_map: TelepLocation.map=c;c=strchr(c,0);c++;break; + case S_location_dir: parm1=GET_WORD(c);TelepLocation.dir=parm1;break; + case S_location_x: TelepLocation.loc_x=GET_WORD(c);TelepLocation.map=0;break; + case S_location_y: TelepLocation.loc_y=GET_WORD(c);TelepLocation.map=0;break; + default: + { + char *d="Chyba v popisu kouzel: Program narazil na neznamou instrukci %d (%02X) pri zpracovani kouzla s cislem %d. Kouzlo bylo ukon‡eno"; + c=alloca(strlen(d)+20); + sprintf(c,d,*(c-1),*(c-1),p->num); + bott_disp_text(c); + spell_end(i,p->cil,p->owner); + return; + } + + + } + while(!ext); + p->start=c-(char *)ablock(H_KOUZLA); + } + +int add_spell(int num,int cil,int owner,char noanim) + { + int i,nl=-1; + TKOUZLO *p; + TKOUZLO *q; + int accnum; + char time_acc=1; + + SEND_LOG("(SPELLS) Casting spell number %d",num,0); + alock(H_KOUZLA); + q=(TKOUZLO *)ablock(H_KOUZLA)+num; + accnum=q->accnum; + if (accnum<0) + { + time_acc=0; + accnum=abs(accnum); + } + if (!accnum) accnum=-1; + for(i=0;iaccnum)!=accnum || spell_table[i]->cil!=cil);i++) + if (spell_table[i]==NULL) nl=i; + if (i==MAX_SPELLS) i=nl; + if (i==-1) + { + SEND_LOG("(ERROR) Too many spells in game!",0,0); + return -1; + } + if (spell_table[i]!=NULL) + { + if (!time_acc) return -1; + spell_end(i,spell_table[i]->cil,spell_table[i]->owner); + } + SEND_LOG("(SPELLS) Current spell number %d was assigned to ID number : %d",num,i); + p=New(TKOUZLO); + vls_table[i]=NewArr(short,24); + memset(vls_table[i],0,2*24); + memcpy(p,q,sizeof(TKOUZLO)); + p->cil=cil; + p->num=num; + p->owner=owner; + p->traceon=noanim; + p->teleport_target=teleport_target; + if (cil>0) p->backfire=(postavy[cil-1].stare_vls[VLS_KOUZLA] & SPL_DEMON)!=0; + aunlock(H_KOUZLA); + spell_table[i]=p; + if (cil>0 && owner>=0) postavy[cil-1].spell=1; + call_spell(i); + return i; + } + +void kouzla_kola(EVENT_MSG *msg,void **unused) + { + unused; + if (msg->msg==E_KOUZLO_KOLO) + { + int i; + + for(i=0;idelay) + { + neco_v_pohybu=1; + if (!(--spell_table[i]->delay)) call_spell(i); + } + } + } + +void kouzla_anm(EVENT_MSG *msg,void **unused) + { + unused; + if (msg->msg==E_KOUZLO_ANM) + { + int i; + + for(i=0;iwait) + { + neco_v_pohybu=1; + if (!(--spell_table[i]->wait)) call_spell(i); + } + } + } + + +char add_group_spell(int num,int sector,int owner,int mode,char noanim) + { + char c=1; + if (mob_map[sector]) + { + int m; + m=mob_map[sector]; + add_spell(num,-m,owner,noanim); + c=0; + if (mobs[m-1].next) add_spell(num,-mobs[m-1].next,owner,noanim); + } + if (map_coord[sector].flags & MC_PLAYER) + { + int i,j; + if (mode==C_nahodna_postava) + { + i=0;j=rnd(POCET_POSTAV)+1; + do + { + if (i>=POCET_POSTAV) i=0; + if (postavy[i].sektor==sector) j--; + if (j) i++; + } + while (j); + add_spell(num,i+1,owner,noanim); + } + else + { + for(i=0;icil==C_kouzelnik) return 1; + if (k->cil==C_postava) return 2; + if (k->cil==C_mrtva_postava) return 3; + if (k->cil==C_postava_jinde) return 4; + return 0; + } + +static word last_sector; + +static char get_valid_sector(word sector) + { + + last_sector=sector; + return 1; + } + + +void cast(int num,THUMAN *p,int owner, char backfire) + { + int i,um,cil,num2; + TKOUZLO *k; + + if (num>511) + { + cil=num>>9; + num2=num & 511; + } + else + { + cil=0; + num2=num; + } + + + SEND_LOG("(SPELLS) Cast num %d cil %d",num2,cil); + k=((TKOUZLO *)ablock(H_KOUZLA))+num2; + SEND_LOG("(SPELLS) Cast spell name %s",k->spellname,0); + + if (cil>0 && k->cil!=C_postava_jinde) + { + THUMAN *h1=postavy+cil-1; + char s[256]; + if ((abs(map_coord[h1->sektor].x-map_coord[p->sektor].x)>5) || + (abs(map_coord[h1->sektor].y-map_coord[p->sektor].y)>5) ) + { + sprintf(s,texty[37+(h1->female==1)],h1->jmeno,p->jmeno); + bott_disp_text(s); + return; + } + } + if (battle && k->traceon & 1 && trace_path(p->sektor,p->direction)==-255) return; + if (!backfire && p->manamge) return; + if (p->vlastnosti[VLS_KOUZLA] & SPL_INVIS) + { + p->stare_vls[VLS_KOUZLA]&=~SPL_INVIS; + prepocitat_postavu(p); + build_all_players(); + } + if (!backfire && (um=p->vlastnosti[VLS_SMAGIE])um) + { + int per1,per2; + if (um*2um) return; + per1=(um-k->um/2)*128/k->um; + per2=rnd(64); + if ((per1/2+32)backfire || (game_extras & EX_RANDOM_BACKFIRES)!=0)) + { + p->mana-=k->mge; + if ((game_extras & EX_RANDOM_BACKFIRES)!=0) + { + labyrinth_find_path(p->sektor,65535,SD_PLAY_IMPS,get_valid_sector,NULL); + teleport_target=last_sector; + cast(rand()*105/RAND_MAX+(cil*512),p,p-postavy,1); + return; + } + cast(k->backfire+(cil<<9),p,owner,1); + return; + } + if(per1mana-=k->mge/2; + return; + } + per1=(64-per1)/2; + per2=rnd(64); + if(per1>per2) p->stare_vls[VLS_SMAGIE]++; + } + + if (!GlobEvent(MAGLOB_BEFOREMAGIC,p->sektor,p->direction)) return; + if (!GlobEvents(MAGLOB_ONSPELLID1,MAGLOB_ONSPELLID9,p->sektor,p->direction,num2)) return; + + if (cil && (k->cil==C_postava || k->cil==C_mrtva_postava || k->cil==C_postava_jinde)) i=add_spell(num2,cil,owner,0); + else + { + if (k->cil==C_policko) if (add_group_spell(num2,p->sektor,owner,C_policko,0)) goto end; + if (k->cil==C_kouzelnik) add_spell(num2,p-postavy+1,owner,0); + if (k->cil==C_policko_pred || k->cil==C_nahodna_postava) + { + int s; + s=p->sektor; + if (!(map_sides[(s<<2)+p->direction].flags & SD_PLAY_IMPS) && !backfire) + s=map_sectors[s].step_next[p->direction]; + if (add_group_spell(num2,s,owner,k->cil,0)) goto end; + } + } + if (!backfire) p->mana-=k->mge; + p->exp+=k->mge; + check_player_new_level(p); + if (p->mana>p->mana_battery) + { + if (p->mana_battery>=0)p->mana=p->mana_battery; + else SEND_LOG("(ERROR) Mana battery error on character %d",p-postavy,0); + p->mana_battery=32767; + } +end: + GlobEvent(MAGLOB_AFTERMAGIC,p->sektor,p->direction); + } + +void mob_cast(int num,TMOB *m,int mob_num) + { + TKOUZLO *k; + + SEND_LOG("(SPELLS) Enemy tries to cast the spell (mob: %d, spell: %d",mob_num,num); + k=((TKOUZLO *)ablock(H_KOUZLA))+num; + switch (k->cil) + { + case C_postava: + case C_kouzelnik:add_spell(num,-(mob_num+1),-1,1);break; + case C_policko:add_group_spell(num,m->sector,-1,C_policko,1);break; + case C_policko_pred: + case C_nahodna_postava: + { + int s; + s=m->sector; + if (!(map_sides[(s<<2)+m->dir].flags & SD_PLAY_IMPS)) + s=map_sectors[s].step_next[m->dir]; + add_group_spell(num,s,-1,k->cil,1); + } + break; + } + } + +static int calculatePhaseDoor(int sector, int dir, int um) +{ + int x=map_coord[sector].x; + int y=map_coord[sector].y; + int stpx=0,stpy=0,diffx=0,diffy=0; + switch (dir) + { + case 0: stpy=-1;diffx=1;break; + case 1: stpx=1;diffy=1;break; + case 2: stpy=1;diffx=1;break; + case 3: stpx=-1;diffy=1;break; + }; + { + int dist=1+rand()*(um/4)/RAND_MAX; + int difs=rand()*2*dist/RAND_MAX-dist; + int newx=x+dist*stpx+difs*diffx; + int newy=y+dist*stpy+difs*diffy; + int i; + int nearest=0; + int nearestdst=0x7FFFFFFF; + + for (i=1;isektor,h->direction,h->vlastnosti[VLS_SMAGIE]); + } + switch (k->cil) + { + case C_nahodna_postava: + case C_postava: + case C_kouzelnik:if (postavy[postava].lives) add_spell(num,postava+1,postava,noanim);break; + case C_mrtva_postava:if (!postavy[postava].lives) add_spell(num,postava+1,postava,noanim);break; + case C_policko:add_group_spell(num,sector,postava,k->cil,noanim);break; + case C_policko_pred: + { + int s; + s=sector; + if (~map_sides[(s<<2)+h->direction].flags & SD_PLAY_IMPS) + s=map_sectors[s].step_next[h->direction]; + add_group_spell(num,s,postava,k->cil,noanim); + } + break; + case C_jiny_cil:if (victim!=NULL) add_spell(num,-(victim-mobs+1),postava,noanim);break; + } + } + +void area_cast(int num,int sector,int owner,char noanim) + { + SEND_LOG("(SPELLS) Area casts the spell (sector: %d, spell: %d)",sector,num); + add_group_spell(num,sector,owner,C_policko,noanim); + } + + + +void kouzla_init() + { + SEND_LOG("(SPELLS) Init...",0,0); + send_message(E_ADD,E_KOUZLO_ANM,kouzla_anm); + send_message(E_ADD,E_KOUZLO_KOLO,kouzla_kola); + memset(spell_table,0,sizeof(spell_table)); + memset(vls_table,0,sizeof(vls_table)); + memset(_flag_map,0,sizeof(_flag_map)); + true_seeing=0; + hlubina_level=0; + show_lives=0; + set_halucination=0; + } + +void reinit_kouzla_full() + { + int i; + + SEND_LOG("(SPELLS) Reinit...",0,0); + for(i=0;iwait) + { + spell_table[i]->wait=0;call_spell(i); + a=1; + } + if (spell_table[i]->cil<0) + { + spell_table[i]->delay=0;call_spell(i); + a=1; + } + } + + } + while(a); + } + + +int save_spells(FILE *f) + { + char res=0; + + int i,s; + + SEND_LOG("(SPELLS) Saving spell table...",0,0); + for(i=0,s=0;iwait) + { + spell_table[i]->wait=0;call_spell(i); + a=1; + } + if (spell_table[i]->cil>0) + { + spell_table[i]->delay=0;call_spell(i); + a=1; + } + } + + } + while(a); + SEND_LOG("(WIZARD) Unaffect... done",0,0); + } + +void unaffect_demon(int cil) + { + int i; + TKOUZLO *spl; + char a; + + + cil++; + SEND_LOG("(SPELLS) Demon returns to astral spaces...",0,0); + for(i=0;spl=spell_table[i],icil==cil) + { + while (spell_table[i]!=NULL) + { + if (spell_table[i]->wait) + { + spell_table[i]->wait=0;call_spell(i); + a=1; + } + if (spell_table[i]->cil>0) + { + spell_table[i]->delay=0;call_spell(i); + a=1; + } + } + } + } + + diff --git a/GAME/MACROS.C b/GAME/MACROS.C new file mode 100644 index 0000000..f313144 --- /dev/null +++ b/GAME/MACROS.C @@ -0,0 +1,794 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include "specproc.h" + +int **macros=NULL; +void *macro_block; +int macro_block_size; +long sound_side_flags=0; //kopie flagu steny pro zvuk +static char codelock_memory[16][8]; +static short rand_value; +static int program_counter=0; +static char trig_group; + +SGlobalEventDef GlobEventList[MAGLOB_NEXTID]; + +void propadnout(int sector); + +#define TRIG_GROUP 1 +#define TRIG_SECTOR 2 + +char get_player_triggered(int p) + { + return (trig_group & (1<=0) trig_group=(char)load; + return trig_group; + } + +void load_macros(int size,void *data) + { + int *r; + + if (macros!=NULL) free(macros); + macros=(int **)getmem(mapsize*sizeof(int *)*4); + memset(macros,0,mapsize*sizeof(char *)*4); + memset(codelock_memory,0,sizeof(codelock_memory)); + r=data; + while (*r) + { + macros[*r]=r+1; + r++; + while(*r) r=(int *)((char *)r+*r+4); + r++; + } + macro_block=data; + macro_block_size=size; + } + +void macro_disp_text(int text,char glob) + { + if (glob) bott_disp_text(texty[text]); + else bott_disp_text(level_texts[text]); + } + +void macro_fireball(TMA_FIREBALL *z,int sector,int dir) + { + LETICI_VEC *fly; + TITEM *it; + + fly=create_fly(); + it=glob_items+z->item-1; + fly->items=NULL; + fly->item=z->item; + fly->xpos=z->xpos; + fly->ypos=z->ypos*128/500-64; + fly->zpos=z->zpos*128/320; + fly->speed=z->speed; + fly->velocity=0; + fly->flags=FLY_IN_FLY | (!it->hmotnost?FLY_NEHMOTNA:0) | (it->flags & ITF_DESTROY?FLY_DESTROY:0)|FLY_NEDULEZITA; + fly->sector=sector; + fly->smer=(dir+2)&3; + fly->owner=0; + fly->hit_bonus=0; + fly->damage=0; + fly->counter=0; + if (fly->flags & FLY_DESTROY)fly->lives=it->user_value; + add_fly(fly); + } + +void macro_sound(TMA_SOUND *p,int psect,int pdir,int sect,int dir) + { + char up=4; + if (sound_side_flags & SD_PRIM_FORV) up=2; + if (~(p->bit16) & up) + if (psect) + play_effekt(map_coord[sect].x,map_coord[sect].y,map_coord[psect].x,map_coord[psect].y,dir,pdir,p); + else + play_effekt(0,0,0,0,-1,-1,p); + } + +void macro_send_act(TMA_SEND_ACTION *p) + { + delay_action(p->s_action,p->sector,p->side,p->change_bits<<24,0,p->delay); + } + +void macro_load_another_map(TMA_LOADLEV *z) + { + int i,j=0; + + if (battle) return; + group_all(); + for(i=0;istart_pos; + } + +void macro_drop_item(int sector,int smer,short item) + { + short itms[2]; + itms[0]=item+1; + itms[1]=0; + push_item(sector,(smer+rnd(2))&0x3,itms); + } + +static void macro_create_item(short item) + { + if (picked_item!=NULL) poloz_vsechny_predmety(); + picked_item=NewArr(short,2); + picked_item[0]=item+1; + picked_item[1]=0; + pick_set_cursor(); + } + + +static char decode_lock(char znak,char *string,char codenum) + { + char *memory; + char *endm; + char *ends; + int i; + + memory=codelock_memory[codenum]; + memmove(memory,memory+1,7); + endm=memory+7; + *endm=znak; + if (!*string) return 1; + ends=string; + for(i=0;i<8;i++,ends++) if (!*ends) break; + ends--; + while (ends>=string) + { + if (*ends!=*endm) break; + ends--;endm--; + } + if (endssector==sector && d->side==dir) + { + if (p==NULL) d_action=d->next;else p->next=d->next; + free(d); + return; + } + p=d; + d=d->next; + } + } + +char if_lock(int side,int key_id,int level,TMA_LOCK *lk) + { + int c; + + level; + if (picked_item==NULL) + { + call_macro(side,MC_LOCKINFO); + return 1; + } + c=picked_item[0]-1; + c=glob_items[c].keynum; + if (c==-1 && level!=-1) + { + int i,j=0,min=-1; + THUMAN *h=postavy; + int thlev; + char s[100]; + + for(i=0;iused && h->groupnum==cur_group && h->vlastnosti[VLS_OBRAT]>min) + {min=h->vlastnosti[VLS_OBRAT];j=i;}; + h=postavy+j; + if (level==0) level=100; + if (level>=min) + if (rnd(100)<=level-min) + { + sprintf(s,texty[158+h->female],h->jmeno); + bott_disp_text(s); + destroy_items(picked_item); + free(picked_item); + picked_item=NULL;pick_set_cursor(); + return 1; + } + thlev=rnd(min); + if (thlev>level) + { + sprintf(s,texty[154+h->female],h->jmeno); + bott_disp_text(s); + //if (abs(level-thlev)<10 && h->vlastnosti[VLS_THIEF]<100) + // { + //h->vlastnosti[VLS_THIEF]++; + //h->stare_vls[VLS_THIEF]++; + //} + lk->thieflevel=1; + return 0; + } + sprintf(s,texty[156+h->female],h->jmeno); + bott_disp_text(s); + return 1; + } + if (c!=key_id || !c) + { + call_macro(side,MC_TOUCHFAIL); + return 1; + } + return 0; + } + +void xchg_block(void *b1,void *b2,int leng) +//#pragma aux xchg_block parm[edi][esi][ecx]= +{ +__asm + { + mov edi,b1 + mov esi,b2 + mov ecx,leng + lp1: mov al,[edi] + mov ah,[esi] + mov [edi],ah + mov [esi],al + inc edi + inc esi + dec ecx + jnz lp1 + } +} + +static void propadnout(int sector) + { + short *i,c,m1,m2; + + for(c=0;c<4;c++) + { + pop_item(sector,c,0,&i); + while(i!=NULL) + { + push_item(sector,c,i); + pop_item(sector,c,0,&i); + } + } + if (mob_map[sector]) + { + m1=mob_map[sector]-1; + m2=mobs[m1].next-1; + mob_map[sector]=0; + if (map_sectors[sector].sector_type==S_DIRA) + { + mobs[m1].sector=map_sectors[sector].sector_tag; + if (m2>=0) mobs[m2].sector=mobs[m1].sector; + } + mob_map[mobs[m1].sector]=m1+1; + } + postavy_propadnout(sector); + } + +static void swap_sectors(TMA_SWAPS *sws) + { + TSECTOR *ss1=&map_sectors[sws->sector1],*ss2=&map_sectors[sws->sector2]; + TSTENA *sd1=&map_sides[sws->sector1<<2],*sd2=&map_sides[sws->sector2<<2]; + char c=4; + char st1=ss2->sector_type,st2=ss1->sector_type; + + for(c=0;c<4;c++) xchg_block(sd1+c,sd2+c,sizeof(TSTENA)); + xchg_block(ss1,ss2,sizeof(TSECTOR)); + if (st1==S_DIRA || st1==S_VODA) propadnout(sws->sector1); + if (st2==S_DIRA || st2==S_VODA) propadnout(sws->sector2); + recheck_button(sws->sector1,0); + recheck_button(sws->sector2,0); + } + +static void hit_1_player(int postava,TMA_WOUND *w,int chaos) + { + int mode=w->pflags>>1; + int zivel=mode-2; + int dostal; + THUMAN *h=postavy+postava; + + if (mode==0) + { + dostal=w->minor+rnd(w->major-w->minor+1); + } + else if (mode==1) + { + short vls[24]; + + memset(vls,0,sizeof(vls)); + vls[VLS_UTOK_L]=w->minor; + vls[VLS_UTOK_H]=w->major; + dostal=vypocet_zasahu(vls,h->vlastnosti,chaos,0,0); + } + else + { + short vls[24]; + + memset(vls,0,sizeof(vls)); + vls[VLS_MGSIL_L]=w->minor; + vls[VLS_MGSIL_H]=w->major; + vls[VLS_MGZIVEL]=zivel; + dostal=vypocet_zasahu(vls,h->vlastnosti,chaos,0,0); + } + player_hit(h,dostal,0); + } + +static void hit_player(TMA_WOUND *w,int sector) + { + int i,pocet,r; + + for(i=0,pocet=0;ipflags & 1) + { + r=rnd(pocet)+1; + for(i=0;i0;i++) if (get_player_triggered(i)) r--; + i--; + hit_1_player(i,w,pocet); + } + else + for(i=0;i=0) + { + m2=mobs[m1].next-1; + if (~mobs[m1].vlajky & MOB_MOBILE && (m2<0 || ~mobs[m2].vlajky & MOB_MOBILE)) monster_test=1; + } + return !monster_test; + } + +static char monster_in_room(int sector) + { + monster_test=0; + is_monster(sector); + if (!monster_test) labyrinth_find_path(sector,65535,SD_MONST_IMPS,is_monster,NULL); + return monster_test; + } + +static int if_jump(TMA_TWOP *i,int side,int abs_pos) + { + TSTENA *sd=map_sides+side; + int go,test,flag; + char ok=0; + + test=abs(i->parm1)-1; + go=i->parm2; + flag=sd->flags; + if (test<32) ok=(flag & (1<>2);break; + } + if (i->parm1<0) ok=!ok; + if (ok) return go+abs_pos;else return -1; + } + +static int if_have_item(TMA_TWOP *i,int abs_pos) + { + int go,test,ip; + char ok=0; + + test=abs(i->parm1); + go=i->parm2; + for(ip=0;ipparm1<0) ok=!ok; + if (ok) return go+abs_pos;else return -1; + } + +static int ma_randjmp(TMA_TWOP *i,int abs_pos) + { + int go,test; + char ok=0; + + test=i->parm1; + go=i->parm2; + if (rand_value==-1) rand_value=rnd(100); + ok=rand_valueparm1)-1; + go=i->parm2; + ok=(test==act); + if (i->parm1<0) ok=!ok; + if (ok) return go+abs_pos;else return -1; + } + + +static int ma_if_flag(TMA_TWOP *i,int abs_pos) + { + int go,test; + char ok=0; + + test=abs(i->parm1)-1; + go=i->parm2; + ok=test_flag(test); + if (i->parm1<0) ok=!ok; + if (ok) return go+abs_pos;else return -1; + } + +static int ma_picki(TMA_TWOP *i,int abs_pos) + { + int go,test; + char ok=0; + + test=abs(i->parm1); + go=i->parm2; + if (picked_item!=NULL) ok=picked_item[0]==test;else ok=0; + if (i->parm1<0) ok=!ok; + if (ok) return go+abs_pos;else return -1; + } + +static void ma_wbook(TMA_LOADLEV *l) + { + char *s; + s=find_map_path(l->name); + add_text_to_book(s,l->start_pos); + play_fx_at(FX_BOOK); + free(s); + } + +static void ma_send_experience(long what) + { + int maxl,i; + THUMAN *h; + + for(i=0,maxl=0,h=postavy;iused && maxllevel) maxl=h->level; + for(i=0,h=postavy;iused && h->lives) + { + h->exp+=what*h->level/maxl; + check_player_new_level(h); + } + bott_draw(0); + } + +static void ma_move_group(int where,int turn,char effect) + { + if (!save_load_trigger(-1)) return; + if (!effect) + { + int i; + THUMAN *h=postavy; + for(i=0;isektor=where,h->direction=turn; + viewsector=where; + viewdir=turn; + } + else + { + THUMAN *h=postavy; + int i; + int sctr; + char kdo=0; + for(i=0;i=0) trig_group|=1<used && h->groupnum==cur_group) trig_group|=1<>=2; + for(i=0,h=postavy;iused && h->sektor==side) trig_group|=1<twop.parm2-q->twop.parm1+1); + x+=q->twop.parm1; + x=create_item_money(x)-1; + if (x) macro_drop_item(sect,side,x); + } + +void macro_change_music(int textindex) +{ + char *trackdef=level_texts[textindex]; + char *nextTrack; + + create_playlist(trackdef); + play_next_music(&nextTrack); + change_music(nextTrack); +} + +void macro_register_global_event(TMULTI_ACTION *q) +{ + GlobEventList[q->globe.event].cancel=q->globe.cancel; + GlobEventList[q->globe.event].sector=q->globe.sector; + GlobEventList[q->globe.event].side=q->globe.side; + GlobEventList[q->globe.event].param=q->globe.param; + if (q->globe.event>=MAGLOB_ONTIMER1 && q->globe.event<=MAGLOB_ONTIMER4) + { + if (GlobEventList[q->globe.event].param>0) + GlobEventList[q->globe.event].param+=game_time; + else + { + long den=24*60*6; + long cas=((-GlobEventList[q->globe.event].param/100)*60+(-GlobEventList[q->globe.event].param%100))*6; + long curtm=game_time % den; + if (cas<=curtm) cas+=den; + GlobEventList[q->globe.event].param=game_time-curtm+cas; + } + } +} + +void call_macro_ex(int side,int flags, int runatside); + +void call_macro(int side,int flags) +{ + call_macro_ex(side,flags,side); +} + + + +void call_macro_ex(int side,int flags, int runatside) + { + TMULTI_ACTION *z,*p; + int *r; + int mcsiz; + int c; + short saved_trigger; + short ls=last_send_action; + short save_rand; + + if (side>=mapsize*4) return; + if (runatside>=mapsize*4) return; + save_rand=rand_value;rand_value=-1; + r=macros[runatside]; + program_counter=0; + if (r==NULL) return; + SEND_LOG("(MULTIACTIONS) Start: Side %.1f Call %X",(float)(runatside/4)+((float)(runatside & 3)/10),flags); + saved_trigger=save_load_trigger(-1); + if (flags & (MC_PASSSUC | MC_PASSFAIL | MC_EXIT)) build_trig_group(TRIG_GROUP,0);else build_trig_group(TRIG_SECTOR,side); + while ((mcsiz=*r)!=0) + { + r++; + zde: + z=(TMULTI_ACTION *)r; + if (z->general.flags & flags) + { + c=-1; + switch (z->general.action) + { + case MA_GEN:break; + case MA_SOUND:macro_sound(&z->sound,side>>2,side & 3,viewsector,viewdir);break; + case MA_TEXTG:macro_disp_text(z->text.textindex,1);break; + case MA_TEXTL:macro_disp_text(z->text.textindex,0);break; + case MA_SENDA:macro_send_act(&z->send_a);break; + case MA_FIREB:macro_fireball(&z->fireball,side>>2,side & 3);break; + case MA_DESTI:if (picked_item!=NULL) + { + destroy_items(picked_item); + free(picked_item); + picked_item=NULL; + pick_set_cursor(); + } + break; + case MA_LOADL:macro_load_another_map(&z->loadlev);break; + case MA_DROPI:macro_drop_item(side>>2,side & 0x3,z->dropi.item);break; + case MA_CREAT:macro_create_item(z->dropi.item);break; + case MA_DIALG:start_dialog(z->text.textindex,-1);break; + case MA_SSHOP:enter_shop(z->text.textindex);break; + case MA_CLOCK:z->general.cancel=decode_lock(z->clock.znak,z->clock.string,z->clock.codenum);break; + case MA_CACTN:cancel_action(z->cactn.sector,z->cactn.dir);break; + case MA_LOCK :z->general.cancel=if_lock(side,z->lock.key_id,z->lock.thieflevel,&z->lock);break; + case MA_SWAPS:swap_sectors(&z->swaps);break; + case MA_WOUND:hit_player(&z->wound,side>>2);break; + case MA_IFJMP:c=if_jump(&z->twop,side,program_counter);break; + case MA_STORY:write_story_text(level_texts[z->text.textindex]);break; + case MA_HAVIT:c=if_have_item(&z->twop,program_counter);break; + case MA_SNDEX:ma_send_experience(z->twop.parm1);break; + case MA_IFACT:c=ma_test_action(&z->twop,ls,program_counter);break; + case MA_CALLS:if (call_map_event(z->twop.parm1,side>>2,side & 3,z->twop.parm2,flags)) call_macro(side,MC_SPEC_SUCC);break; + case MA_MOVEG:ma_move_group(z->twop.parm1,z->twop.parm2 & 3,z->twop.parm2>>7);break; + case MA_PLAYA:ma_play_anim(z->loadlev.name,z->loadlev.dir);break; + case MA_ISFLG:c=ma_if_flag(&z->twop,program_counter);break; + case MA_CHFLG:change_flag(z->twop.parm1,(char)z->twop.parm2);break; + case MA_CUNIQ:macro_drop_item(side>>2,side & 0x3,create_unique_item(&z->uniq.item)-1);break; + case MA_MONEY:ma_drop_money(side>>2,side & 0x3,z);break; + case MA_GUNIQ:macro_create_item(create_unique_item(&z->uniq.item)-1);break; + case MA_PICKI:c=ma_picki(&z->twop,program_counter);break; + case MA_WBOOK:ma_wbook(&z->loadlev);break; + case MA_RANDJ:c=ma_randjmp(&z->twop,program_counter);break; + case MA_ENDGM:unwire_proc();send_message(E_CLOSE_MAP,(void *)255);break; + case MA_GOMOB:ma_control_mob(z->twop.parm1,z->twop.parm2);break; + case MA_SHRMA:call_macro_ex(side,flags,z->twop.parm1*4+z->twop.parm2);break; + case MA_MUSIC:macro_change_music(z->text.textindex);break; + case MA_GLOBE:macro_register_global_event(z);break; + } + if (c!=-1) p=go_macro(runatside,c);else p=NULL; + if (p!=NULL) {r=(int *)p;program_counter=c;mcsiz=r[-1];goto zde;} + if (z->general.once) + { + z->general.action=0; + z->general.once=0; + if (z->general.cancel) + { + z->general.cancel=0; + goto end; + } + } + if (z->general.cancel) return; + } + r=(int *)((char *)r+mcsiz); + program_counter++; + } + end: + rand_value=save_rand; + save_load_trigger(saved_trigger); + SEND_LOG("(MULTIACTIONS) End: Side %.1f Call %X",(float)(runatside/4)+((float)(runatside & 3)/10),flags); + } + +static char lock_saved=255; +static char lock_empty=254; + + +char save_codelocks(FILE *fsta) + { + char *c; + int i; + + c=(char *)&codelock_memory; + i=sizeof(codelock_memory); + while(*c==0 && i) c++,i--; + if (!i) + { + SEND_LOG("(SAVELOAD) Codelocks wasn't used in this map... not saved",0,0); + return !fwrite(&lock_empty,sizeof(lock_empty),1,fsta); + } + SEND_LOG("(SAVELOAD) Storing code-locks...",0,0); + if (!fwrite(&lock_saved,sizeof(lock_saved),1,fsta)) return 1; + return !fwrite(codelock_memory,sizeof(codelock_memory),1,fsta); + } + + +char load_codelocks(FILE *fsta) + { + char c; + + if (!fread(&c,sizeof(lock_empty),1,fsta)) return 1; + if (c!=lock_saved) + { + if (c!=lock_empty) + { + fseek(fsta,-1,SEEK_CUR); //uprav pripadne stare verze savegamu ktere nemaji codelocky + SEND_LOG("(ERROR) Invalid value for codelocks... may be it's old version of savegame",0,0); + } + memset(codelock_memory,0,sizeof(codelock_memory)); + return 0; + } + SEND_LOG("(SAVELOAD) Restoring code-locks for this map...",0,0); + return !fread(codelock_memory,sizeof(codelock_memory),1,fsta); + } + diff --git a/GAME/MENU.C b/GAME/MENU.C new file mode 100644 index 0000000..df89ec7 --- /dev/null +++ b/GAME/MENU.C @@ -0,0 +1,599 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include "engine1.h" +#include +#include "globals.h" + + +#define MUSIC "TRACK06.MUS" + +#define H_ANIM_ORIGN (H_MENUS_FREE+0) +#define H_ANIM (H_MENUS_FREE+1) +#define H_MENU_BAR (H_MENUS_FREE+31) +#define H_MENU_MASK (H_MENUS_FREE+32) +#define H_MENU_ANIM (H_MENUS_FREE+33) +#define H_PICTURE (H_MENUS_FREE+39) + +#define SELECT 1 +#define UNSELECT -1 + +#define SPEED 3 +int speedscroll=3; +char low_mem=0; +static volatile char load_ok=0; + +static cur_pos[]={0,0,0,0,0}; +static cur_dir[]={UNSELECT,UNSELECT,UNSELECT,UNSELECT,UNSELECT}; + +static titlefont=H_FBIG; + +#define TITLE_HEAD 1 +#define TITLE_NAME 2 +#define TITLE_TEXT 3 +#define TITLE_CENTER 0 +#define TITLE_KONEC 4 + +static title_mode=0; +static title_line=0; + +#define CLK_MAIN_MENU 4 + +static char vymacknout(int id,int xa,int ya,int xr,int yr) + { + + for(id=0;id<5;id++) cur_dir[id]=UNSELECT; + xa,ya,xr,yr; + return 1; + } + +static char promacknuti(int id,int xa,int ya,int xr,int yr) + { + char *z; + word *w; + + z=ablock(H_MENU_MASK);w=(word *)z; + z+=6+512; + z+=xr+yr*w[0]; + vymacknout(id,xa,ya,xr,yr); + if (*z!=0) cur_dir[*z-1]=SELECT; + return 1; + } + +static char click(int id,int xa,int ya,int xr,int yr) + { + int i; + + id,xa,ya,xr,yr; + for(i=0;i<5;i++) if (cur_dir[i]==SELECT) break; + if (i!=5) send_message(E_MENU_SELECT,i); + return 1; + } + + +T_CLK_MAP clk_main_menu[]= + { + {-1,220,300,220+206,300+178,promacknuti,1,-1}, + {-1,220,300,220+206,300+178,click,2,-1}, + {-1,0,0,639,479,vymacknout,1,-1}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + +void rozdily(void *orign,void *obr,void *hicolor,void *xtab,int pocet) +//#pragma aux rozdily parm[EDX][ESI][EDI][EBX][ECX]= +{ +__asm + { + mov edx,orign + mov esi,obr + mov edi,hicolor + mov ebx,xtab + mov ecx,pocet + +jp1:lodsb + xor al,[edx] + movzx eax,al + inc edx + movzx eax,short ptr[ebx+eax*2] + stosw + dec ecx + jnz jp1 + } +} + +static void nahraj_rozdilovy_pcx(void **pp,long *s) + { + char *org,*pos; + char *vysl; + word *size,*paltab; + word *hicolor,*p; + void *origin; + int siz; + + load_pcx((char *)*pp,*s,A_8BIT,&vysl); + size=(word *)vysl; + free(*pp); + siz=size[0]*size[1]; + p=hicolor=getmem(siz*2+12); + *p++=size[0]; + *p++=size[1]; + *p++=16; + origin=ablock(H_ANIM_ORIGN); + org=(char *)origin+6+512; + pos=(char *)vysl+6+512; + paltab=(word *)vysl+3; + rozdily(org,pos,hicolor+3,paltab,siz); + free(vysl); + *pp=hicolor; + *s=_msize(*pp); + } + + +static void init_menu_entries(void) + { + int i; + char *a; + def_handle(H_ANIM_ORIGN,"LOGO00.PCX",pcx_8bit_decomp,SR_BGRAFIKA); + def_handle(H_ANIM,"LOGO00.PCX",pcx_15bit_decomp,SR_BGRAFIKA); + a=alloca(15); + for(i=1;i<30;i++) + { + sprintf(a,"LOGO%02d.PCX",i); + def_handle(H_ANIM+i,a,nahraj_rozdilovy_pcx,SR_BGRAFIKA); + } + def_handle(H_MENU_BAR,"MAINMENU.PCX",pcx_8bit_decomp,SR_BGRAFIKA); + def_handle(H_MENU_MASK,"MENUVOL5.PCX",pcx_8bit_decomp,SR_BGRAFIKA); + for(i=0;i<5;i++) + { + sprintf(a,"MENUVOL%d.PCX",i); + def_handle(H_MENU_ANIM+i,a,pcx_15bit_decomp,SR_BGRAFIKA); + } + } + +void zobraz_podle_masky_asm(char barva,void *scr,void *data, void *maska,int xs,int ys) +//#pragma aux zobraz_podle_masky_asm parm[al][edi][esi][ebx][edx][ecx]= + { + __asm + { + mov al,barva + mov edi,scr + mov esi,data + mov ebx,maska + mov edx,xs + mov ecx,ys + push ebp + mov ebp,edx + jp3: cmp al,[ebx] + jnz jp1 + movsw + jmp jp2 +jp1: add edi,2 + add esi,2 +jp2: inc ebx + dec edx + jnz jp3 + mov edx,ebp + add edi,scr_linelen + sub edi,edx + sub edi,edx + dec ecx + jnz jp3 + pop ebp + } + } + +static void zobraz_podle_masky(char barva,char anim) + { + char *maska; + word *data; + word *obr=GetScreenAdr()+300*scr_linelen2+220; + word xs,ys; + + alock(H_MENU_MASK); + maska=ablock(H_MENU_MASK); + data=ablock(H_MENU_ANIM+anim); + xs=data[0]; + ys=data[1]; + zobraz_podle_masky_asm(barva,obr,data+3,maska+6+512,xs,ys); + aunlock(H_MENU_MASK); + } + +static void prehraj_animaci_v_menu(EVENT_MSG *msg,char **unused) + { + static counter=0; + unused; + if (msg->msg==E_TIMER) + { + if (counter % SPEED==0) + { + int i=counter/SPEED;char show=0; + + schovej_mysku(); + if (!low_mem || ~i & 1)put_picture(0,56,ablock(H_ANIM+i)); + do_events(); + for(i=0;i<5;i++) + { + cur_pos[i]+=cur_dir[i]; + if (cur_pos[i]<0) cur_pos[i]=0; + else if (cur_pos[i]>4) cur_pos[i]=4; + else + { + zobraz_podle_masky(i+1,cur_pos[i]); + do_events(); + show=1; + } + } + ukaz_mysku(); + update_mysky(); + showview(0,56,640,250); + if (show) showview(220,300,206,178); + } + counter++; + if (counter>=(SPEED*30)) counter=0; + } + } + + +static void preload_anim(va_list args) + { + int i; + + low_mem=0; + ablock(H_ANIM+29); + for(i=0;i<30;i+=2) + { + apreload(H_ANIM+i); + task_sleep(NULL); + } + for(i=1;i<30;i+=2) + { + THANDLE_DATA *h; + + h=get_handle(H_ANIM+29); + if (h->status!=BK_PRESENT) + { + low_mem=1; + break; + } + apreload(H_ANIM+i); + task_sleep(NULL); + } + for(i=0;i<5;i++) + { + apreload(H_MENU_ANIM+i); + task_sleep(NULL); + } + apreload(H_MENU_MASK); + task_wait_event(E_TIMER); + load_ok=1; + } + +static void klavesnice(EVENT_MSG *msg,void **unused) + { + short cursor,i; + unused; + + + if (msg->msg==E_KEYBOARD) + { + for(cursor=0;cursor<5;cursor++) if (cur_dir[cursor]==SELECT) break; + if (cursor==5) cursor=-1; + + switch(*((char *)msg->data+1)) + { + case 'H':cursor--;if (cursor<0) cursor=0;break; + case 'P':cursor++;if (cursor>4) cursor=4;break; + case 28: + case 57:click(0,0,0,0,0);return; + } + for(i=0;i<5;i++) if (i==cursor) cur_dir[i]=SELECT;else cur_dir[i]=UNSELECT; + } + } + +int enter_menu(char open) + { + char c; + char *d; + init_menu_entries(); + add_task(2048,preload_anim); + load_ok=0; + while(!load_ok) task_sleep(NULL); + if (!open) + { + play_next_music(&d); + change_music(d); + } + update_mysky(); + schovej_mysku(); + curcolor=0;bar(0,0,639,479); + put_picture(0,0,ablock(H_MENU_BAR)); + put_picture(0,56,ablock(H_ANIM)); + ukaz_mysku(); + if (open) effect_show(NULL);else showview(0,0,0,0); + change_click_map(clk_main_menu,CLK_MAIN_MENU); + send_message(E_ADD,E_TIMER,prehraj_animaci_v_menu); + send_message(E_ADD,E_KEYBOARD,klavesnice); + ms_last_event.event_type=0x1; + send_message(E_MOUSE,&ms_last_event); + d=task_wait_event(E_MENU_SELECT); + c=*d; + disable_click_map(); + send_message(E_DONE,E_KEYBOARD,klavesnice); + cur_dir[c]=UNSELECT; + while (cur_pos[c]) task_wait_event(E_TIMER); + task_wait_event(E_TIMER); + send_message(E_DONE,E_TIMER,prehraj_animaci_v_menu); + return c; + } + +char *get_next_title(char control,char *filename) + { + static FILE *titles=NULL; + static ENCFILE fl; + static char buffer[81]; + char *path,*c; + + switch(control) + { + case 1:concat(path,pathtable[SR_MAP],filename); + titles=enc_open(path,&fl); + if (titles==NULL) + { + concat(path,pathtable[SR_DATA],filename); + titles=enc_open(path,&fl); + if (titles==NULL) + { + char popis[300]; + closemode(); + sprintf(popis,"Soubor nenalezen: %s%s nebo %s%s\n",pathtable[SR_MAP],filename,pathtable[SR_DATA],filename); + MessageBox(NULL,popis,NULL,MB_OK|MB_ICONSTOP); + exit(1); + } + } + return (char *)titles; + case 0:if (titles!=NULL)fgets(buffer,80,titles); + c=strchr(buffer,'\n');if (c!=NULL) *c=0; + return buffer; + case -1:if (titles!=NULL)enc_close(&fl); + break; + } + return NULL; + } + +static int title_lines[640][2]; + +static int insert_next_line(int ztrata) + { + char *c; + int ll=-1; + RedirectScreenBufferSecond(); + do + { + if (title_mode!=TITLE_KONEC) c=get_next_title(0,NULL);else c[0]=0; + if (c[0]=='*') + { + strupr(c); + if (!strcmp(c+1,"HEAD")) + { + title_mode=TITLE_HEAD; + set_font(titlefont,RGB(146,187,142)); + } + else if (!strcmp(c+1,"NAME")) + { + title_mode=TITLE_NAME; + set_font(titlefont,RGB(186,227,182)); + } + else if (!strcmp(c+1,"CENTER")) + { + title_mode=TITLE_CENTER; + set_font(titlefont,RGB(255,248,240)); + } + else if (!strcmp(c+1,"TEXT")) + { + title_mode=TITLE_TEXT; + set_font(titlefont,RGB(255,248,240)); + } + else if (!strcmp(c+1,"KONEC")) + { + title_mode=TITLE_KONEC; + } + else if (!strncmp(c+1,"LINE",4)) + { + sscanf(c+5,"%d",&title_line); + } + else if (!strncmp(c+1,"SMALL",5)) titlefont=H_FBOLD; + else if (!strncmp(c+1,"BIG",3)) titlefont=H_FBIG; + else if (!strncmp(c+1,"SPEED",5)) sscanf(c+6,"%d",&speedscroll); + } + else + { + ll=text_height(c); + if (ll==0) ll=text_height("W"); + if (ll0) + { + if (skip>10) skip=10; + newc+=skip*speedscroll; + scan_lines(buff,360,skip); + scroll_and_copy((word *)picture+640*60+3,buff,scr,360,skip,title_lines); + //memcpy(GetScreenAdr(),buff,480*scr_linelen); + get_max_extend(&l,&r); + memmove(title_lines,&title_lines[skip],sizeof(title_lines)-skip*sizeof(int)*2); + //showview(l,60,r-l+1,360); + showview(0,60,639,360); + buff+=scr_linelen2*359; + memcpy(buff,buff+scr_linelen2*skip,40*scr_linelen); + showview(0,0,640,40); + task_wait_event(E_TIMER); + counter+=skip; + lcounter-=skip; + } + else + if (skip<0) counter=skip; + while (lcounter<=0 && !end) + { + int c; + c=insert_next_line(lcounter); + scan_lines(GetBuffer2nd(),360+lcounter,-lcounter); + if (c==-1) + { + end=1; + lcounter=360; + } + else + lcounter+=c; + } + } + while (!(task_quitmsg() || (end && lcounter<=0))); + ukaz_mysku(); + get_next_title(-1,NULL); + aunlock(H_PICTURE); + if (send_back)send_message(E_KEYBOARD,27); + } + +void run_titles(va_list args) + { + int task_id; + task_id=add_task(8196,titles,1,"titulky.TXT"); + task_wait_event(E_KEYBOARD); + term_task(task_id); + } + +void konec_hry() + { + int task_id; + int timer; + char *d; + + schovej_mysku(); + curcolor=0; + bar(0,0,639,479); + effect_show(NULL); + create_playlist(texty[205]); + play_next_music(&d); + change_music(d); + timer=get_timer_value(); + while (get_timer_value()-timer<150) task_sleep(NULL); + task_id=add_task(8196,titles,1,"ENDTEXT.TXT"); + task_wait_event(E_KEYBOARD); + if (is_running(task_id)) term_task(task_id); + task_wait_event(E_TIMER); + task_wait_event(E_TIMER); + task_id=add_task(8196,titles,0,"TITULKY.TXT"); + task_wait_event(E_KEYBOARD); + if (is_running(task_id)) term_task(task_id); + change_music("?"); + curcolor=0; + bar(0,0,639,479); + ukaz_mysku(); + effect_show(NULL); + timer=get_timer_value(); + while (get_timer_value()-timer<150) task_sleep(NULL); + } + diff --git a/GAME/REALGAME.C b/GAME/REALGAME.C new file mode 100644 index 0000000..a4721e8 --- /dev/null +++ b/GAME/REALGAME.C @@ -0,0 +1,1997 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include "inicfg.h" + + + +#define A_OPEN_DOOR 1 +#define A_CLOSE_DOOR 2 +#define A_OPEN_CLOSE 3 +#define A_RUN_PRIM 4 +#define A_SHOW_PRIM 5 +#define A_HIDE_PRIM 6 +#define A_SHOW_HIDE_PRIM 7 +#define A_RUN_SEC 8 +#define A_SHOW_SEC 9 +#define A_HIDE_SEC 10 +#define A_SHOW_HIDE_SEC 11 +#define A_HIDE_PRIM_SEC 12 +#define A_DISPLAY_TEXT 13 +#define A_CODELOCK_LOG 14 +#define A_OPEN_TELEPORT 15 +#define A_CLOSE_TELEPORT 16 +#define A_CODELOCK_LOG2 17 + +#define MAX_FLY_SECT 4 + +#define DIS (char *)0x1 +#define START_HANDLE hl_ptr + +extern TSTR_LIST texty_v_mape; + +static TSTR_LIST leaving_places=NULL; + +char pass_zavora=0; + +char map_with_password=0; + +MAPGLOBAL mglob={ + "","","","",0,0,0,1 +}; +TSTENA *map_sides; +TSECTOR *map_sectors; +TVYKLENEK *map_vyk; //mapa vyklenku +word vyk_max; //pocet vyklenku v mape +short **map_items; +char *flag_map; +TMAP_EDIT_INFO *map_coord; +TSTR_LIST level_texts; +int mapsize; +int num_ofsets[10]; //tabulka ofsetu pro cisla sten k levelu +char sekceid[]=""; +char datapath; +D_ACTION *d_action={NULL}; +int end_ptr; +char cur_group=1; +char group_select=1; +char cancel_pass=0; +char break_sleep=0; +char enable_sort=0; +int sleep_ticks=MAX_SLEEP; +char side_touched=1; +char save_map=1; +//char formace=0; +char last_send_action; //naposled vyslana akce +char insleep=0; +short moving_player=0; + +char force_start_dialog=0; +int start_dialog_number=0; +int start_dialog_mob=0; + +long money=0; + +char runes[5]={0,0,0,0,0}; + +char group_sort[POCET_POSTAV]={0,1,2,3,4,5}; + +long load_section(FILE *f,void **section, int *sct_type,long *sect_size) +// + { + long s; + char c[20]; + + *section=NULL; + fread(c,1,sizeof(sekceid),f); + if (strcmp(c,sekceid)) return -1; + fread(sct_type,1,sizeof(*sct_type),f); + fread(sect_size,1,sizeof(*sect_size),f); + fread(&s,1,sizeof(s),f); + *section=getmem(*sect_size); + s=fread(*section,1,*sect_size,f); + return s; + } + + +void prepare_graphics(int *ofs,char *names,long size,void *decomp,int class) + { + char *p,*end; + + end=names+size; + p=names; + while (p640) pos=640; + curcolor=RGB555(16,16,16);hor_line(0,476,pos); + curcolor=RGB555(8,8,8);hor_line(0,477,pos); + curcolor=RGB555(31,31,31);hor_line(0,475,pos); + showview(0,460,640,20); + do_events(); + } + +void preload_objects(int ofsts) +//#pragma preload_objects parm []; + { + int i; + char lodka=1; + char c[200]; + + for(i=1;iH_LODKA7 || lodka) apreload_sign(i,ofsts); + } + apreload_start(preload_percent); +/* for(i=0;inext;} + calc_fly(); + save_map=1; + free(map_sides); + free(map_sectors); + free(flag_map); + free(map_coord); + free(map_vyk);map_vyk=NULL;vyk_max=0; + if (texty_v_mape!=NULL)release_list(texty_v_mape); + while (d_action!=NULL) + { + void *p=d_action; + d_action=d_action->next; + free(p); + } + texty_v_mape=NULL; + release_list(level_texts); + if (mob_map!=NULL) free(mob_map); + if (macro_block!=NULL) + { + free(macro_block); + free(macros); + macros=NULL; + macro_block=NULL; + macro_block_size=0; + } + if (map_items!=NULL) + { + for(i=0;iloadproc==pcx_fade_decomp) zneplatnit_block(i); + } + for(i=hl_ptr;i>=24; + flags&=0x1f; + return q->flags ^ flags; + } + +void recheck_button(int sector,char auto_action) + { + TSECTOR *ts; + short **ms; + char swch; + char flrpls[]={1,2,2,4,4,8,2,2}; + + ts=map_sectors+sector; + if (ts->sector_type!=S_TLAC_OFF && ts->sector_type!=S_TLAC_ON) return; + ms=map_items+(sector<<2); + swch=(map_coord[sector].flags & MC_DPLAYER || mob_map[sector] || + ms[0]!=NULL || ms[1]!=NULL || ms[2]!=NULL || ms[3]!=NULL); + switch (ts->sector_type) + { + case S_TLAC_OFF:if (swch) + { + ts->floor+=flrpls[ts->flags & 7]; + ts->sector_type=S_TLAC_ON; + if (auto_action) do_action(ts->action,ts->sector_tag,ts->side_tag,0,0); + } + break; + case S_TLAC_ON:if (!swch) + { + ts->floor-=flrpls[ts->flags & 7]; + ts->sector_type=S_TLAC_OFF; + if (auto_action) do_action(ts->action,ts->sector_tag,ts->side_tag,0,0); + } + break; + } + } + +void stop_fly(LETICI_VEC *p,char zvuk) + { + if (zvuk && ~p->flags & FLY_NEDULEZITA)sirit_zvuk(p->sector); + if (!(p->flags & FLY_DESTROY)) + { + item_sound_event(p->items==NULL?p->item:p->items[0],p->sector); + if (p->xpos>=0) push_item(p->sector,(p->smer+(p->ypos>0))&3,p->items); + else push_item(p->sector,(p->smer+(p->ypos<0)+2)&3,p->items); + } + p->flags |= FLY_BURNT; + } + +void interrupt_fly(LETICI_VEC *p) + { + if (p->flags & FLY_DESTROY_SEQ) return; + p->speed=0; + if (p->flags & FLY_DESTROY) + { + p->flags|=FLY_DESTROY_SEQ|FLY_NEHMOTNA; + p->anim_pos=3; + p->velocity=0; + item_sound_event(p->items==NULL?p->item:p->items[0],p->sector); + } + else + if (p->velocity==0) stop_fly(p,1);else if (p->velocity<10) p->velocity=10; + } + +LETICI_VEC *create_fly() + { + LETICI_VEC *p,*q; + + p=letici_veci; + q=NULL; + while (p!=NULL) if (p->flags & FLY_UNUSED) + { + if (q==NULL) letici_veci=p->next;else q->next=p->next; + free(p->items); + break; + } + else + { + q=p; + p=p->next; + } + if (p==NULL) p=New(LETICI_VEC); + p->flags=0; + p->items=NULL; + p->item=0; + p->lives=0; + return p; + } + +TFLY *duplic_fly(TFLY *p) + { + TFLY *q; + + q=create_fly(); + *q=*p; + if (q->items!=NULL) + { + int s=_msize(q->items); + q->items=(short *)getmem(s); + memcpy(q->items,p->items,s); + } + return q; + } + +void calc_fly() + { + LETICI_VEC *p,*q; + short ss; + + for(p=letici_veci;p!=NULL;p=q) + { + p->xpos+=p->speed; + if (p->flags & FLY_BURNT) + if (p->flags & FLY_UNUSED) + { + short ds[2]; + if (letici_veci==p) letici_veci=p->next; + else + { + for(q=letici_veci;q->next!=p;q=q->next); + q->next=p->next; + } + q=p->next; + ds[0]=p->item;ds[1]=0; + if (p->items!=NULL) destroy_items(p->items); else destroy_items(ds); + free(p->items); + p->items=NULL; + free(p); + continue; + } + else + { + q=p->next; + continue; + } + q=p->next; + if (!(p->flags & FLY_NEHMOTNA)) + { + p->velocity+=1; + } + p->zpos-=p->velocity; + ss=p->sector; + if (!(p->flags & FLY_NEDULEZITA)) neco_v_pohybu=1; + if (p->zpos>110) p->zpos=110; + if (p->zpos<=20) + { + if (map_sectors[p->sector].sector_type==S_DIRA) + { + p->speed=0; + if (p->zpos<=-128) + { + p->sector=map_sectors[p->sector].sector_tag; + p->zpos=256; + } + } + else + stop_fly(p,1); + continue; + } + if (p->flags & FLY_IN_FLY && p->xpos>-16 && zasah_veci(p->sector,p)) + { + interrupt_fly(p); + continue; + } + if (p->xpos>63) + { + p->flags|=FLY_IN_FLY; + p->xpos-=127; + ss=map_sectors[p->sector].step_next[p->smer]; + if (p->sector != 0 && !(map_sides[p->sector*4+p->smer].flags & SD_THING_IMPS)) + { + p->sector=ss; + + if (ISTELEPORTSECT(p->sector)) + p->sector=map_sectors[p->sector].sector_tag; + } + + else + { + p->xpos+=127-p->speed; + if (!zasah_veci(p->sector,p) && p->lives) p->lives--; + if (p->lives) + { + TFLY *q,*z; + + q=duplic_fly(p);q->smer=p->smer+1&3; + z=duplic_fly(p);z->smer=p->smer-1&3; + add_fly(q); + add_fly(z); + } + interrupt_fly(p); + } + } + else if (p->counter++ > 100) { + zasah_veci(p->sector,p); + interrupt_fly(p); + continue; + } + } + + } + +extern long sound_side_flags; + + +void calc_animations() + { + int i; + + for (i=0;iflags; + pj=p->prim_anim>>4;pk=p->prim_anim & 15; + sj=p->sec_anim>>4;sk=p->sec_anim & 15; + if (!pk && !sk) continue; + if (p->flags & SD_PRIM_ANIM) + { + if (p->flags & SD_PRIM_GAB) + if (pj==0 || pj==pk) p->flags^=SD_PRIM_FORV; + if (p->flags & SD_PRIM_FORV) pj++; else pj--; + if (pj>pk) pj=0; + if (pj<0) pj=pk; + } + else + { + if (p->flags & SD_PRIM_FORV) pj++; else pj--; + if (pk && (pj+(!(p->flags & SD_PRIM_FORV))==pk)) + {p->flags&=~0xff;p->flags|=flag_map[i];} + if (pj>pk) pj=pk; + else if (pj<0) pj=0; + else call_macro(i,MC_ANIM|((pj & 1)?MC_ANIM2:0)|(pj?0:MC_CLOSEDOOR)|(pj==pk?MC_OPENDOOR:0)); + if (pk==pj && p->flags & SD_PRIM_GAB) + p->flags&=~SD_PRIM_FORV; + } + if (p->flags & SD_SEC_ANIM) + { + if (p->flags & SD_SEC_GAB) + if (sj==0 || sj==sk) p->flags^=SD_SEC_FORV; + if (p->flags & SD_SEC_FORV) sj++; else sj--; + if (sj>sk) sj=0; + if (sj<0) sj=sk; + } + else + { + if (p->flags & SD_SEC_FORV) sj++; else sj--; + if (!pk && sk && (sj+(!(p->flags & SD_SEC_FORV))==sk)) + {p->flags&=~0xff;p->flags|=flag_map[i];} + if (sj>sk) sj=sk; + else if (sj<0) sj=0; + else if (!pk) call_macro(i,MC_ANIM|((sj & 1)?MC_ANIM2:0)|(pj?0:MC_CLOSEDOOR)); + if (sk==sj && p->flags & SD_SEC_GAB) + p->flags&=~SD_SEC_FORV; + } + p->prim_anim=(pj<<4)+pk; + p->sec_anim=(sj<<4)+sk; + } + sound_side_flags=0; + } + + +void delay_action(int action_numb,int sector,int direct,int flags,int nosend,int delay) + { + D_ACTION *d; + if (!sector && !direct) return; + if (!delay) do_action(action_numb,sector,direct,flags,nosend); + else + { + d=(D_ACTION *)getmem(sizeof(D_ACTION)); + d->action=action_numb; + d->sector=sector; + d->side=direct; + d->flags=flags>>16; + d->nocopy=nosend; + d->delay=delay; + d->next=d_action; + d_action=d; + } + } +/* +int get_action_delay(TSTENA *q) + { + if (q->flags & SD_DELAY) + { + if (q->sec) return q->sec_anim & 0xf; + return q->prim_anim & 0xf; + } + else + return 0; + } +*/ +void check_codelock_log(int sector,unsigned long flags) + { + int i; + TSTENA *p; + TSECTOR *s; + p=&map_sides[sector*4]; + s=&map_sectors[sector]; + for (i=0;i<4;i++) if (!(p[i].flags & SD_PRIM_VIS)) break; + if (i==4) do_action(s->action,s->sector_tag,s->side_tag,flags,0); + } + + +int do_action(action_numb,sector,direct,flags,nosend) + { + TSTENA *q; + TSECTOR *s; + char *c; + int sid; + char ok=0; + + sid=sector*4+direct; + s=&map_sectors[sector]; + q=&map_sides[sid]; + c=&flag_map[sid]; + switch (action_numb) + { + case 0: + q->flags=actn_flags(q,flags); + break; + case A_OPEN_DOOR: + if (!(q->flags & SD_PRIM_FORV) && !(q->flags & SD_PRIM_ANIM)) + { + q->flags|=SD_PRIM_FORV; + *c=(char)actn_flags(q,flags); + ok=1; + } + if (!(q->flags & SD_SEC_FORV)) + { + q->flags|=SD_SEC_FORV; + ok=1; + } + sound_side_flags=q->flags; + break; + case A_CLOSE_DOOR: + if (q->flags & SD_PRIM_FORV && !(q->flags & SD_PRIM_ANIM)) + { + q->flags&=~SD_PRIM_FORV; + *c=(char)actn_flags(q,flags); + ok=1; + } + if (q->flags & SD_SEC_FORV) + { + q->flags&=~SD_SEC_FORV; + ok=1; + } + sound_side_flags=q->flags; + break; + case A_OPEN_CLOSE: + if (!(q->flags & SD_PRIM_ANIM)) q->flags^=SD_PRIM_FORV | SD_SEC_FORV; + else q->flags^= SD_SEC_FORV ; + *c=(char)actn_flags(q,flags); + ok=1; + sound_side_flags=q->flags; + break; + case A_RUN_PRIM: + q->flags|=SD_PRIM_ANIM; + ok=1; + break; + case A_HIDE_PRIM: + if (q->flags & SD_PRIM_VIS) + { + q->flags&=~SD_PRIM_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + } + break; + case A_SHOW_PRIM: + if (!(q->flags & SD_PRIM_VIS)) + { + q->flags|=SD_PRIM_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + } + break; + case A_SHOW_HIDE_PRIM: + q->flags^=SD_PRIM_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + break; + case A_RUN_SEC: + q->flags|=SD_SEC_ANIM; + ok=1; + break; + case A_HIDE_SEC: + if (q->flags & SD_SEC_VIS) + { + q->flags&=~SD_SEC_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + } + break; + case A_SHOW_SEC: + if (!(q->flags & SD_SEC_VIS)) + { + q->flags|=SD_SEC_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + } + break; + case A_SHOW_HIDE_SEC: + q->flags^=SD_SEC_VIS; + *c=(q->flags=actn_flags(q,flags)); + ok=1; + break; + case A_HIDE_PRIM_SEC: + if ((q->flags & SD_SEC_VIS)||(q->flags & SD_PRIM_VIS)) + { + q->flags&=~(SD_SEC_VIS+SD_PRIM_VIS); + *c=(q->flags=actn_flags(q,flags)); + ok=1; + } + break; + case A_DISPLAY_TEXT: + bott_disp_text(level_texts[sector]); + ok=1; + return 0; + case A_CODELOCK_LOG2: + check_codelock_log(sector,flags); + q->flags^=SD_PRIM_VIS; + check_codelock_log(sector,flags); + ok=1; + break; + case A_CODELOCK_LOG: + check_codelock_log(sector,0x1f000000); + q->flags^=SD_PRIM_VIS; + check_codelock_log(sector,0x1f000000); + ok=1; + break; + case A_OPEN_TELEPORT: + ok=(s->sector_type!=S_TELEPORT); + s->sector_type=S_TELEPORT; + { + int i; + for(i=0;i<4;i++) map_sides[(sector<<2)+i].flags|=SD_SEC_VIS; + } + nosend=1; + break; + case A_CLOSE_TELEPORT: + ok=(s->sector_type==S_TELEPORT); + s->sector_type=S_NORMAL; + { + int i; + for(i=0;i<4;i++) map_sides[(sector<<2)+i].flags&=~SD_SEC_VIS; + } + nosend=1; + break; + } + if (nosend) return 0; + last_send_action=action_numb; + call_macro(sid,MC_INCOMING); + if (ok) + { + ok=0; + call_macro(sid,MC_SUCC_DONE); + } + if (q->flags & SD_COPY_ACTION) + { + + q->flags&=~SD_COPY_ACTION; + delay_action(action_numb,q->sector_tag,q->side_tag,flags,0,0); + q->flags|=SD_COPY_ACTION; + } + if (q->flags & SD_SEND_ACTION) + { + + q->flags&=~SD_SEND_ACTION; + delay_action(q->action,q->sector_tag,q->side_tag,q->flags,0,0); + q->flags|=SD_SEND_ACTION; + } + if (q->flags & SD_APPLY_2ND && s->step_next[direct]) + do_action(action_numb,s->step_next[direct],(direct+2)&3,flags,1); + return 0; + } + +/* +void black(int i,int sector,int dir) + { + int xl,y1,xr,y2; + + if (!(map_sides[sector*4+dir].flags & SD_INTERIER)) return; + y2=MIDDLE_Y+points[i][0][VIEW3D_Z].y+16; + y1=MIDDLE_Y+points[i][1][VIEW3D_Z].y+16; + if (i<0) + { + xl=MIDDLE_X-points[i][0][VIEW3D_Z].x; + xr=MIDDLE_X-points[i+1][0][VIEW3D_Z].x; + } + else + if (i>0) + { + xl=MIDDLE_X+points[i-1][0][VIEW3D_Z].x; + xr=MIDDLE_X+points[i][0][VIEW3D_Z].x; + } + else + { + xl=MIDDLE_X-points[0][0][VIEW3D_Z].x; + xr=MIDDLE_X+points[0][0][VIEW3D_Z].x; + } + if (xl<0) xl=0; + if (xr>639) xr=639; + curcolor=back_color; + bar(xl,y1,xr,y2); + } +*/ + +void do_delay_actions() + { + D_ACTION *d,*p,*q; + + d=d_action;p=NULL; + while (d!=NULL) + { + if (!(--d->delay)) + { + q=d; + if (q==d_action) + { + d_action=d->next; + d=d_action; + } + else + { + p=d_action; + while (p->next!=d) p=p->next; + p->next=d->next; + d=p->next; + } + do_action(q->action,q->sector,q->side,q->flags<<16,q->nocopy); + free(q); + } + else + { + d=d->next; + } + } + } + +void mrtva_skupina() + { + int i=0; + + for(i=0;!postavy[i].groupnum || !postavy[i].used;i++); + zmen_skupinu(&postavy[i]); + } +/* +static void check_pod_vodou(char mode) + { + short sectors[POCET_POSTAV]; + short psec; + short pp=0; + int i,j; + + + for(i=0;ikondice) h->kondice-=ziv*2; + else + { + player_hit(h,h->lives,0); + } + if (h->kondice<0) h->kondice=0; + bott_draw(0); + } + +void check_players_place(char mode) + { + int i; + THUMAN *h=postavy; + char vir_eff=0; + static char vir_zavora=0; + char levitat; + + for(i=0;iused && h->lives) + { + int sect; + int u1; + + levitat=(h->vlastnosti[VLS_KOUZLA] & SPL_LEVITATION)!=0; + sect=h->sektor; + if (sect>=mapsize) continue; + switch (map_sectors[sect].sector_type) + { + case S_ACID:if (!levitat) + if (h->lives>3) {h->lives-=3;bott_draw(0);} + else + player_hit(h,3+7*mode,0); + break; + case S_VIR: + if (!levitat) + if (mode==0 && vir_zavora==0) + { + int i,smer; + vir_zavora=1;pass_zavora=0; + smer=rnd(100)<50?-1:1; + if (vir_eff==0) + for(i=0;i<8;i++) turn_zoom(smer); + vir_eff=1; + vir_zavora=0; + cancel_pass=1; + } + else + break; + case S_LAVA: if (!levitat) + { + u1=(h->lives); + player_hit(h,u1,0); + bott_draw(0); + } + else + { + if (h->lives>3) {h->lives-=3;bott_draw(0);} + else + player_hit(h,3+7*mode,0); + } + + break; + case S_SSMRT: + u1=(h->lives); + player_hit(h,u1,0); + bott_draw(0); + break; + case S_VODA: + if (!levitat) + akce_voda(h,mode);break; + case S_DIRA:if (!pass_zavora) postavy_propadnout(sect);break; + case S_LODKA:if (lodka!=1 && mode) + { + set_backgrnd_mode(1);lodka=1; + } + break; + } + if (mglob.map_effector==ME_PVODA && ~map_coord[h->sektor].flags & MC_SAFEPLACE) akce_voda(h,mode); + if (map_sectors[sect].sector_type!=S_LODKA && lodka) + { + set_backgrnd_mode(0);lodka=0; + } + } + } + +static void move_lodka(int oldsect,int newsect) + { + if (map_sectors[oldsect].sector_type==S_LODKA && + map_sectors[newsect].sector_type==S_VODA) + { + map_sectors[oldsect].sector_type=S_VODA; + map_sectors[newsect].sector_type=S_LODKA; + } + } + +void calc_game() + { + int d; + calc_animations(); + if (d_action!=NULL) do_delay_actions(); + calc_mobs(); + if (force_start_dialog && !norefresh && !cancel_render) + { + force_start_dialog=0; + call_dialog(start_dialog_number,start_dialog_mob); + } + check_players_place(0); + if ((d=check_end_game())!=0) + if (d==1) wire_end_game();else mrtva_skupina(); + if (battle && cur_mode!=MD_INBATTLE) + { + start_battle(); + } + else if(!battle && select_player!=-1) + { + select_player=-1; + bott_draw(0); + } + } + +void a_touch(sector,dir) + { + TSTENA *q; + int sid; + + sid=sector*4+dir; + q=&map_sides[sid]; + if (q->flags & SD_PASS_ACTION) return; + if (q->sec && ~q->flags & SD_SEC_VIS) return; + side_touched=1; + if (!q->sec) delay_action(q->action,q->sector_tag,q->side_tag,q->flags,0,0); + else + if (q->flags & SD_SEC_VIS) + { + if (q->flags & SD_AUTOANIM) do_action(A_OPEN_CLOSE,sector,dir,0,1); + delay_action(q->action,q->sector_tag,q->side_tag,q->flags,0,0); + } + call_macro(sid,MC_TOUCHSUC); + } + +void a_pass(sector,dir) + { + TSTENA *q; + + q=&map_sides[sector*4+dir]; + q->flags&=~SD_SECRET; + if (q->flags & SD_ALARM) + { + if (GlobEvent(MAGLOB_ALARM,viewsector,viewdir)) + sirit_zvuk(map_sectors[sector].step_next[dir]); + } + if (!(q->flags & SD_PASS_ACTION)) return; + delay_action(q->action,q->sector_tag,q->side_tag,q->flags,0,0); + } + +void zmen_skupinu(THUMAN *p) + { + int i; + + if (p->groupnum==0) {bott_draw(0);return;} + cur_group=p->groupnum; + for(i=0;isektor; + viewdir=p->direction; + schovej_mysku(); + bott_draw(0); + other_draw(); + ukaz_mysku(); + showview(0,378,640,480); + ukaz_mysku(); + cancel_render=1; + } + +void sort_groups() + { + int i,j,t=0; + + if (cur_mode==MD_PRESUN) group_sort[0]=moving_player; + if (enable_sort) + { + for(i=0;iused && h->groupnum==1 && h->sektor!=viewsector) break; + if (i==POCET_POSTAV) cur_group=1; + } + for(i=0,h=postavy;iused && h->lives && h->sektor==viewsector) h->groupnum=cur_group; + } + + bott_draw(0); + } + +void destroy_player_map() //je nutne volat pred presunem postav + { + int i; + for(i=0;isektor].flags|=(p->lives?MC_PLAYER:MC_DEAD_PLR); + if (mglob.map_effector==ME_PVODA) + { + if (q_item_one(i,water_breath+1))map_coord[p->sektor].flags|=MC_SAFEPLACE; + } + } + } + + +char chod_s_postavama(char sekupit) + { + int i,/*j,*/lastsec=-1; + char marks[6]; + char gatt=0; + signed char group_nums[7]; + + destroy_player_map(); + if (cur_mode==MD_PRESUN) + { + postavy[select_player].sektor=viewsector; + postavy[select_player].direction=viewdir; + } + else + { + memset(group_nums,0xff,sizeof(group_nums)); + group_nums[0]=0; + for(i=0;iused && h1->lives && !marks[group_sort[i]]) + { + int sc; + int ss=(sc=h1->sektor)<<2; + for(dir=0;dir<4;dir++) if (map_sectors[sc].step_next[dir]==lastsec && ~map_sides[ss+dir].flags & SD_PLAY_IMPS) break; + if (dir!=4) + { + for(j=0,h2=postavy;jused && h2->lives && h2->groupnum==h1->groupnum) + { + h2->sektor=lastsec; + h2->direction=dir; + h2->utek=1; + marks[j]=1; + } + lastsec=sc; + attach=1; + gatt=1; + group_nums[h1->groupnum]=gr++; + } + } + if (!attach) break; + } + for(i=1;i<7;i++) if (group_nums[i]==-1) group_nums[i]=gr++; + for(i=0;imsg==E_INIT || msg->msg==E_DONE) return; + check_all_mobs(); + calc_game();msg;data; + SEND_LOG("(GAME) STEP",0,0); + } + +void do_halucinace() + { + hal_sector=rnd(mapsize-1)+1; + hal_dir=rnd(4); + } + +void sector0(void) + { + int i; + + for(i=0;iused && h->groupnum==grp && h->lives && + (h->vlastnosti[VLS_POHYB]==0 || h->kondice==0)) return 0; + return 1; + } + +void step_zoom(char smer) + { + char nopass,drs; + int sid,nsect,sect; + char can_go=1; + + if (running_anm) return; + if (pass_zavora) return; + if (lodka && (smer==1 || smer==3)) return; + cancel_pass=0; + drs=(viewdir+smer)&3; + sid=viewsector*4+drs; + sect=viewsector; + call_macro(sid,MC_EXIT); + nopass=(map_sides[sid].flags & SD_PLAY_IMPS); + if (nopass) call_macro(sid,MC_PASSFAIL);else call_macro(sid,MC_PASSSUC); + if (cur_mode==MD_PRESUN) + { + select_player=moving_player; + if(!postavy[select_player].actions) nopass=1; + } + else can_go=test_can_walk(cur_group); + if (!can_go) + { + bott_disp_text(texty[220]); + return; + } + if (force_start_dialog) cancel_pass=1; + if (cancel_pass) return; + if (!GlobEvent(MAGLOB_ONSTEP,viewsector,viewdir)) return; + if (viewsector!=sect) nsect=viewsector,viewsector=sect;else nsect=map_sectors[viewsector].step_next[drs]; + if (map_sectors[nsect].sector_type==S_SCHODY) + { + int i; + viewdir=(viewdir+map_sectors[nsect].side_tag) & 3; + nsect=map_sectors[nsect].sector_tag; + i=mob_map[nsect]; + while (i!=0) + { + i--; + mobs[i].sector=mobs[i].home_pos; + i=mobs[i].next; + } + mob_map[nsect]=0; + } + else if (mob_map[nsect] && !nopass) + if (!battle){ if (!mob_alter(nsect)) return; } + else return; + if (map_sectors[nsect].sector_type==S_LODKA) + { + int i; + THUMAN *h; + group_all();can_go=1; + for(i=0,h=postavy;igroupnum!=cur_group && h->lives) break; + if (i!=POCET_POSTAV) + { + bott_disp_text(texty[66]); + return; + } + } + pass_zavora=1; + norefresh=1; + schovej_mysku(); + anim_sipky(H_SIPKY_S+smer,1); + anim_sipky(0,255); + hide_ms_at(385); + ukaz_mysku(); + if (set_halucination) do_halucinace(); + if (loadlevel.name[0]) + { + if (!battle) + { + pass_zavora=0; + return; + } + nopass=1; + loadlevel.name[0]=0; + exit_wait=0; + } + if (!can_go) nopass=1; + if (!nopass) + { + a_pass(viewsector,drs); + viewsector=nsect; + move_lodka(sect,nsect); + chod_s_postavama(1); + send_message(E_KROK); + } + if (!cancel_pass) + { + render_scene(viewsector,viewdir); + if (smer==2) + { + OutBuffer2nd(); + if (!nopass) shift_zoom(smer); + } + else + { + shift_zoom(smer); + OutBuffer2nd(); + if (nopass) shift_zoom(smer+2); + } + if (battle || (game_extras & EX_ALWAYS_MINIMAP)) draw_medium_map(); + sort_groups(); + bott_draw(0); + other_draw(); + } + update_mysky(); + ukaz_mysku(); + if (!cancel_render) showview(0,0,0,0); + norefresh=0; + cancel_render=1; + mix_back_sound(0); + viewsector=postavy_propadnout(viewsector); + check_postavy_teleport(); + recheck_button(sect,1); + recheck_button(viewsector,1); + check_players_place(1); + cancel_pass=0; + pass_zavora=0; + if (force_start_dialog) + { + force_start_dialog=0; + call_dialog(start_dialog_number,start_dialog_mob); + } + if (cur_mode==MD_GAME) recalc_volumes(viewsector,viewdir); + } + +void turn_zoom(int smer) + { + if (running_anm) return; + if (pass_zavora) return;else pass_zavora=1; + if (!GlobEvent(MAGLOB_ONTURN,viewsector,viewdir)) return; + if (set_halucination) do_halucinace(); + norefresh=1; + hold_timer(TM_BACK_MUSIC,1); + viewdir=(viewdir+smer)&3; + render_scene(viewsector,viewdir); + hide_ms_at(387); + if (smer==1) + { + anim_sipky(H_SIPKY_SV,1); + anim_sipky(0,255); + turn_left(); + } + else + { + anim_sipky(H_SIPKY_SZ,1); + anim_sipky(0,255); + turn_right(); + } + chod_s_postavama(0); + OutBuffer2nd(); + if (battle || (game_extras & EX_ALWAYS_MINIMAP)) draw_medium_map(); + other_draw(); + update_mysky(); + ukaz_mysku(); + showview(0,0,0,0); + recalc_volumes(viewsector,viewdir); + if (!battle) calc_game(); + norefresh=0; + cancel_render=1; + hold_timer(TM_BACK_MUSIC,0); + mix_back_sound(0); + pass_zavora=0; + } + +int check_path(word **path,word tosect) + { + word *p,*n,ss; + char ok; + int i; + + p=*path; + n=p+1;ok=0; + while (*p!=tosect) + { + if (map_sectors[*n].sector_type!=S_DIRA && ISTELEPORTSECT(*n)) + { + for(i=0;i<4 && map_sectors[*p].step_next[i]!=*n;i++) + if (i==4) + { + ss=*p; + free(*path);*path=NULL; + return ss; + } + if (!map_sides[(*p<<2)+i].flags & SD_PLAY_IMPS) ok=1; + } + if (!ok) + { + ss=*p; + free(*path);*path=NULL; + najdi_cestu(*p,tosect,SD_PLAY_IMPS,path,0); + if (*path==NULL) return ss; + p=*path; + n=p+1; + a_touch(ss,i); + } + p++;n++; + ok=0; + } + free(*path);*path=NULL; + return tosect; + } + +void recall() + { + int tosect,max,i,j; + word *paths[POCET_POSTAV]; + + for(i=0;imsg==E_KEYBOARD) break_sleep=1; + if (msg->msg==E_MOUSE) + { + MS_EVENT *ms; + + ms=get_mouse(msg); + if (ms->event_type & (0x2+0x8+0x20)) break_sleep=1; + } + } + +void sleep_players(va_list args) + { + int i; + int hours=0; + char reg; + char enablity; + + if (!sleep_ticks) return; + if (!GlobEvent(MAGLOB_STARTSLEEP,viewsector,viewdir)) return; + enablity=enable_sound(0); + mute_all_tracks(0); + autosave(); + insleep=1; + update_mysky(); + schovej_mysku(); + curcolor=0;bar(0,17,639,360+16); + send_message(E_ADD,E_KEYBOARD,key_break_sleep); + ukaz_mysku(); + showview(0,0,0,0); + unwire_proc(); + break_sleep=0; + while (sleep_ticks && !break_sleep) + { + reg=0; + if (!(sleep_ticks%6)) + { + if ((reg=(sleep_ticks%HODINA==0))==1) + { + char s[50]; + for(i=0;imsg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + while (_bios_keybrd(_KEYBRD_READY) ) _bios_keybrd(_KEYBRD_READ); + switch (c) + { + case 'H':step_zoom(0);break; + case 'P':step_zoom(2);break; + case 'M':if (GetKeyState(VK_CONTROL) & 0x80) + step_zoom(1); + else + turn_zoom(1); + break; + case 'K':if (GetKeyState(VK_CONTROL) & 0x80) + step_zoom(3); + else + turn_zoom(-1); + break; + case 79: + case 's':step_zoom(3);break; + case 81: + case 't':step_zoom(1);break; + case 0x21:if (q_item(flute_item,viewsector)) bott_draw_fletna(); + case 57:a_touch(viewsector,viewdir);if (cur_mode==MD_PRESUN)send_message(E_KEYBOARD,28*256);break; + case 15: + case 50: + if (GlobEvent(MAGLOB_BEFOREMAPOPEN,viewsector,viewdir)) + show_automap(1); + break; + case 0x17:unwire_proc(); + wire_inv_mode(human_selected);break; +// case 'A':lodka=!lodka;set_backgrnd_mode(lodka);break; + case 1:konec(0,0,0,0,0);break; +// case 25:GamePause();break; + case 28:enforce_start_battle();break; + case 82:group_all();break; + case '<':if (!battle && GlobEvent(MAGLOB_CLICKSAVE,viewsector,viewdir)) + {unwire_proc();cancel_render=1;wire_save_load(1);}break; + case '=':unwire_proc();cancel_render=1;wire_save_load(0);break; + case '>':game_setup(0,0,0,0,0);break; + CASE_KEY_1_6:c=group_sort[c-2]; + if (postavy[c].sektor==viewsector && postavy[c].used) + add_to_group(c); + zmen_skupinu(postavy+c); + bott_draw(1); + break; +/* default: + { + char s[20]; + bott_disp_text(itoa(c,s,10)); + break; + }*/ + } + } + return &game_keyboard; + } + + +void start_dialog(int dialog,int mob) + { + if (battle) + { + call_dialog(dialog,mob); + } + else + { + force_start_dialog=1; + start_dialog_number=dialog; + start_dialog_mob=mob; + } +// call_dialog(dialog,mob); + } + + +int postavy_propadnout(int sector) + { + char redraw=0; + int i,z=sector; + mute_hit_sound=0; + if (map_coord[sector].flags & MC_DPLAYER && map_sectors[sector].sector_type==S_DIRA) + { + for(i=0;i + +#define DELITEL 0xC005 + + +unsigned long vysledek; + +main() + { + int i; + for(i=0;i<65535;i++) + { + vysledek=DELITEL*i; + printf("%08X ",vysledek); + } + } diff --git a/GAME/SETUP.C b/GAME/SETUP.C new file mode 100644 index 0000000..c2790d4 --- /dev/null +++ b/GAME/SETUP.C @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "engine1.h" +#include +#include "globals.h" +#include +#include + +extern char enable_sort; +extern char autoattack; + + +char q_runsetup(char *parm) + { + char c[6]; + + strncpy(c,parm,6); + strupr(c); + return !strncmp(c,"/SETUP",6); + } + + +static void show_setup_desktop(WINDOW *w) + { + put_picture(w->x,w->y,ablock(H_SETUPBAR)); + } + +static void checkbox_animator(THE_TIMER *t) + { + t; + animate_checkbox(10,130,10); + } + +static int effects[]={SND_GVOLUME,SND_MUSIC,SND_GFX,SND_TREBL,SND_BASS,SND_XBASS}; + +static void do_setup_change() + { + char c; + + c=f_get_value(0,o_aktual->id); + switch (o_aktual->id) + { + case 10:set_snd_effect(SND_SWAP,c & 1);break; + case 20:set_snd_effect(SND_OUTFILTER,c & 1);break; + default:set_snd_effect(effects[o_aktual->id/10-20],c);break; + } + } + +static void change_zoom() + { + int id=o_aktual->id; + int i; + + for(i=30;i<60;i+=10) c_set_value(0,i,f_get_value(0,i) & ~1 | (i==id)); + zoom_speed((id-30)/10); + } + +static void change_turn() + { + int id=o_aktual->id; + int i; + + for(i=60;i<90;i+=10) c_set_value(0,i,f_get_value(0,i) & ~1 | (i==id)); + turn_speed((id-60)/10); + } + +void unwire_setup(); + +static EVENT_PROC(setup_keyboard) + { + user_ptr; + WHEN_MSG(E_KEYBOARD) + { + if (GET_DATA(char)==27) + { + unwire_proc(); + } + } + } + +static void wire_setup() + { + unwire_proc(); + unwire_proc=unwire_setup; + mute_all_tracks(0); + cur_mode=MD_SETUP; + send_message(E_ADD,E_KEYBOARD,setup_keyboard); + SEND_LOG("(GAME) Starting setup",0,0); + } + +static void unwire_setup() + { + show_names=f_get_value(0,90) & 1; + enable_sort=f_get_value(0,100) & 1; + autoattack=f_get_value(0,110) & 1; + autosave_enabled=f_get_value(0,120) & 1; + level_preload=f_get_value(0,130) & 1; + delete_from_timer(TM_CHECKBOX); + mix_back_sound(32768); + close_current(); + send_message(E_DONE,E_KEYBOARD,setup_keyboard); + wire_proc(); + cancel_render=1; + SEND_LOG("(GAME) Setup closed",0,0); + } + +char exit_setup(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + unwire_setup(); + return 0; + } + +T_CLK_MAP setup[]= + { + {-1,0,0,639,14,exit_setup,2,H_MS_DEFAULT}, + {-1,0,15,639,479,exit_setup,0x8,H_MS_DEFAULT}, + }; + + +void skeldal_checkbox(OBJREC *); +void setup_ok_button(OBJREC *); +void skeldal_soupak(OBJREC *); + + + + +void new_setup() + { + WINDOW *w; + CTL3D ctl; + int i; + static int textxp[]={ 75, 75,435,435,434,535,535,535,434,434,434,434,434, 35,410,510}; + static int textyp[]={275,305, 65, 95,125, 65, 95,125,185,215,245,275,305,235, 40, 40}; + static int textc[]={ 53, 54, 56, 57, 58, 56, 57, 58,140,141,142,143,144 ,51, 55, 59}; + + mix_back_sound(256000-16384); + memset(&ctl,0,sizeof(ctl)); + change_click_map(setup,4); + set_font(H_FBOLD,SETUP_COL2); + default_font=curfont; + memcpy(f_default,charcolors,sizeof(f_default)); + w=create_window(0,SCREEN_OFFLINE,639,359,0,&ctl); + w->draw_event=show_setup_desktop; + desktop_add_window(w); + define(10,50,270,190,20,0,skeldal_checkbox); c_default(get_snd_effect(SND_SWAP)); on_change(do_setup_change); + if (check_snd_effect(SND_OUTFILTER)) + { + define(20,50,300,190,20,0,skeldal_checkbox);c_default(get_snd_effect(SND_OUTFILTER)); + on_change(do_setup_change); + } + + define(30,410,60,90,20,0,skeldal_checkbox);c_default(zoom_speed(-1)==0); + on_change(change_zoom); + define(40,410,90,90,20,0,skeldal_checkbox);c_default(zoom_speed(-1)==1);on_change(change_zoom); + define(50,410,120,90,20,0,skeldal_checkbox);c_default(zoom_speed(-1)==2);on_change(change_zoom); + + define(60,510,60,90,20,0,skeldal_checkbox);c_default(turn_speed(-1)==0);on_change(change_turn); + define(70,510,90,90,20,0,skeldal_checkbox);c_default(turn_speed(-1)==1);on_change(change_turn); + define(80,510,120,90,20,0,skeldal_checkbox);c_default(turn_speed(-1)==2);on_change(change_turn); + + for(i=0;i<5;i++) + { + define((i+9)*10,410,180+i*30,190,20,0,skeldal_checkbox); + switch(i) + { + case 0:c_default(show_names);break; + case 1:c_default(enable_sort);break; + case 2:c_default(autoattack);break; + case 3:c_default(autosave_enabled);break; + case 4:c_default(level_preload);break; + } + } + + for(i=0;imsg==E_INIT) + { + volsave=get_snd_effect(SND_GVOLUME); + set_snd_effect(SND_GVOLUME,volsave>>1); + } + if (msg->msg==E_KEYBOARD) + { + set_snd_effect(SND_GVOLUME,volsave); + wire_main_functs(); + msg->msg=-2; + } + } + +void GamePause() + { + int i; + unwire_proc(); + send_message(E_ADD,E_KEYBOARD,GameResume); + update_mysky(); + schovej_mysku(); + trans_bar(0,0,640,480,0); + set_font(H_FBOLD,RGB555(0,23,0)); + i=text_width(texty[5]); + add_window(320-(i/2)-10,100,i+40,40,H_IDESKA,4,20,20); + redraw_window(); + set_aligned_position(320,115,1,1,texty[5]); + outtext(texty[5]); + ukaz_mysku(); + showview(0,0,0,0); + cancel_render=1; + } + +/*void user_setup() + { + + initmode256(cur_xlat); + init_mysky(); + hranice_mysky(0,0,639,479); + mouse_set_default(H_MS_DEFAULT); + ukaz_mysku(); + setup_dialoge(); + escape(); + schovej_mysku(); + closemode(); + } + */ diff --git a/GAME/SKELDAL.C b/GAME/SKELDAL.C new file mode 100644 index 0000000..24e8d88 --- /dev/null +++ b/GAME/SKELDAL.C @@ -0,0 +1,1755 @@ +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#include "engine1.h" +#include "wizard.h" +#include "version.h" +#include + +#define CONFIG_NAME SKELDALINI + +#define INI_TEXT 1 +#define INI_INT 2 + +#define ERR_GENERAL 1 +char def_path[]=""; +char graph_path[]="graphics\\"; +char basc_graph[]="graphics\\basic\\"; +char item_graph[]="graphics\\items\\"; +char sample_path[]="samples\\"; +char font_path[]="font\\"; +char map_path[]="maps\\"; +char music_path[]="music\\"; +char org_music_path[]="music\\"; +char temp_path[]="?"; +char enemies_path[]="graphics\\enemies\\"; +char video_path[]="video\\"; +char dialogs_path[]="graphics\\dialogs\\"; +char saves_path[]=""; +char work_path[]=""; +char cd_path[]=""; +char map2_path[]=""; +char plugins_path[]=""; +char *pathtable[]={def_path,graph_path,sample_path,font_path,map_path,music_path,temp_path,basc_graph,item_graph,enemies_path,video_path,dialogs_path,saves_path,work_path,cd_path,map2_path,plugins_path,org_music_path}; + +/* +char *pathtable[]= + {"", + "graphics\\", + "graphics\\basic\\", + "graphics\\items\\", + "samples\\", + "font\\", + "maps\\", + "music\\", + "", + "graphics\\enemies\\", + "video\\", + "graphics\\dialogs\\" + }; +*/ + +char **texty; + +char skip_intro=0; +char autosave_enabled=0; +long game_time=0; +int charmin=3; +int charmax=3; + +int autoopenaction=0; +int autoopendata=0; + +void *cur_xlat; + +void redraw_desktop_call(); + +TMA_LOADLEV loadlevel; + +typedef struct inis + { + char heslo[15]; + char parmtype; + }INIS; + +THE_TIMER timer_tree; + + +int hl_ptr=H_FIRST_FREE; +int debug_enabled=0; +char sound_detection=1; +int snd_devnum,snd_parm1,snd_parm2,snd_parm3,snd_mixing=22000; +char gamespeed=6; +char gamespeedbattle=0; +char level_preload=1; +char *level_fname=NULL; +int game_extras=0; + +char default_map[20]="LESPRED.MAP"; + +THUMAN postavy[POCET_POSTAV],postavy_save[POCET_POSTAV]; +void (*unwire_proc)(); +void (*wire_proc)(); +char cur_mode,battle_mode; +static init_music_vol=127,init_gfx_vol=255; +static char full_video=0; +static char titles_on=0; +static char windowed=0; +static char windowedzoom=1; +static char monitor=0; +static int refresh=0; + +void pcx_fade_decomp(void **p,long *s); +void pcx_15bit_decomp(void **p,long *s); +void pcx_15bit_autofade(void **p,long *s); +void pcx_15bit_backgrnd(void **p,long *s); +void pcx_8bit_decomp(void **p,long *s); + +char *texty_knihy; +static char *patch_file=NULL; +int cur_page=0; + +TSTR_LIST cur_config=NULL; + +TDREGISTERS registred[]= + { + {H_DESK,"desk.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_TOPBAR,"topbar.pcx",pcx_15bit_decomp,SR_BGRAFIKA}, + {H_OKNO,"okno.pcx",pcx_15bit_decomp,SR_BGRAFIKA}, + {H_MS_DEFAULT,"msc_sip.pcx", pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MS_SOUBOJ,"msc_x.pcx", pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MS_WHO,"msc_who.pcx", pcx_8bit_decomp,SR_BGRAFIKA}, +// {H_MS_LIST,"msc_list.pcx", pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MS_ZARE,"msc_zare.pcx", pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KOMPAS,"kompas.pcx", pcx_15bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_S,"sipky_s.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_SV,"sipky_sv.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_SZ,"sipky_sz.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_V,"sipky_v.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_Z,"sipky_z.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_J,"sipky_j.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_BACKMAP,"backmap.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_FBOLD,"sada16.fon",NULL,SR_FONT}, + {H_FSYMB,"ikones.fon",NULL,SR_FONT}, + {H_FLITT,"font4x8.fon",NULL,SR_FONT}, + {H_FLITT5,"font5x8.fon",NULL,SR_FONT}, + {H_FONT6,"font6x9.fon",NULL,SR_FONT}, + {H_FONT7,"sada7.fon",NULL,SR_FONT}, + {H_FTINY,"tiny.fon",NULL,SR_FONT}, + {H_FKNIHA,"kniha.fon",NULL,SR_FONT}, + {H_FBIG,"timese.fon",NULL,SR_FONT}, + {H_IOBLOUK,"ioblouk.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_LODKA,"lodka.pcx",pcx_15bit_decomp,SR_BGRAFIKA}, + {H_IDESKA,"ideska.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_IMRIZ1,"imriz1.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RAMECEK,"ramecek.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_ENEMY,"enemy.dat",NULL,SR_MAP}, + {H_BATTLE_BAR,"souboje.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_BATTLE_MASK,"m_souboj.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MZASAH1,"mzasah1.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MZASAH2,"mzasah2.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_MZASAH3,"mzasah3.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_PZASAH,"pzasah.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_BATTLE_CLICK,"souboje2.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SIPKY_END,"sipky.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KOUZLA,"kouzla.dat",NULL,SR_MAP}, + {H_LEBKA,"death.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KOSTRA,"bones.pcx",pcx_fade_decomp,SR_BGRAFIKA}, + {H_RUNEHOLE,"runehole.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RUNEMASK,"runemask.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_POWERBAR,"powerbar.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_POWERLED,"powerled.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_POSTAVY_DAT,"postavy.dat",NULL,SR_MAP}, + {H_SOUND_DAT,"sound.dat",NULL,SR_MAP}, + {H_SND_SWHIT1,"swd_hit0.wav",wav_load,SR_ZVUKY}, + {H_SND_SWHIT2,"swd_hit1.wav",wav_load,SR_ZVUKY}, + {H_SND_SWMISS1,"swd_mis0.wav",wav_load,SR_ZVUKY}, + {H_SND_SWMISS2,"swd_mis1.wav",wav_load,SR_ZVUKY}, + {H_SND_SIP1,"sip2.wav",wav_load,SR_ZVUKY}, + {H_SND_SIP2,"sip1.wav",wav_load,SR_ZVUKY}, + {H_SND_KNIHA,"kniha.wav",wav_load,SR_ZVUKY}, + {H_SND_OBCHOD,"obchod.wav",wav_load,SR_ZVUKY}, + {H_SND_LEKTVAR,"lektvar.wav",wav_load,SR_ZVUKY}, + {H_SND_TELEPIN,"telepin.wav",wav_load,SR_ZVUKY}, + {H_SND_TELEPOUT,"telepout.wav",wav_load,SR_ZVUKY}, + {H_SND_HEK1M,"jauu1m.wav",wav_load,SR_ZVUKY}, + {H_SND_HEK2M,"jauu2m.wav",wav_load,SR_ZVUKY}, + {H_SND_HEK1F,"jauu1f.wav",wav_load,SR_ZVUKY}, + {H_SND_HEK2F,"jauu2f.wav",wav_load,SR_ZVUKY}, + {H_SND_EAT,"jidlo.wav",wav_load,SR_ZVUKY}, + {H_SND_WEAR,"obleci.wav",wav_load,SR_ZVUKY}, + {H_SND_PUTINV,"put_inv.wav",wav_load,SR_ZVUKY}, + {H_RUNEBAR1,"r_ohen.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RUNEBAR2,"r_voda.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RUNEBAR3,"r_zeme.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RUNEBAR4,"r_vzduch.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_RUNEBAR5,"r_mysl.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SPELLDEF,"spelldef.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KNIHA,"kniha.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_WINTXTR,"wintxtr.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SAVELOAD,"saveload.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SVITEK,"svitek.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_LOADTXTR,"loadtxtr.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_DIALOG,"dialog.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_DIALOGY_DAT,"dialogy.dat",NULL,SR_MAP}, + {H_SHOP_PIC,"shop.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_TELEPORT,"teleport.mgf",NULL,SR_BGRAFIKA}, + {H_FX,"fx.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_CHECKBOX,"checkbox.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SETUPBAR,"volbades.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SOUPAK,"volbasou.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_SETUPOK,"volbazpe.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_POSTUP,"postup.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_LODKA0,"lesda21a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA1,"lesda22a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA2,"lesda23a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA3,"lesda24a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA4,"lesda25a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA5,"lesda26a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA6,"lesda27a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_LODKA7,"lesda28a.pcx",pcx_fade_decomp,SR_GRAFIKA}, + {H_FLETNA,"fletna.wav",wav_load,SR_ZVUKY}, + {H_FLETNA_BAR,"stupnice.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_FLETNA_MASK,"stupni_m.pcx",pcx_8bit_nopal,SR_BGRAFIKA}, + {H_SND_SEVER,"sever.wav",wav_load,SR_ZVUKY}, + {H_SND_VYCHOD,"vychod.wav",wav_load,SR_ZVUKY}, + {H_SND_JIH,"jih.wav",wav_load,SR_ZVUKY}, + {H_SND_ZAPAD,"zapad.wav",wav_load,SR_ZVUKY}, + {H_SND_RAND1,"random1.wav",wav_load,SR_ZVUKY}, + {H_SND_RAND2,"random2.wav",wav_load,SR_ZVUKY}, + {H_SND_RAND3,"random3.wav",wav_load,SR_ZVUKY}, + {H_SND_RAND4,"random4.wav",wav_load,SR_ZVUKY}, + {H_CHARGEN,"chargen.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_CHARGENB,"chargenb.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_CHARGENM,"chargenm.pcx",pcx_8bit_nopal,SR_BGRAFIKA}, + {H_BGR_BUFF,"",set_background,SR_BGRAFIKA}, + {H_KREVMIN,"krevmin.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KREVMID,"krevmid.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + {H_KREVMAX,"krevmax.pcx",pcx_8bit_decomp,SR_BGRAFIKA}, + + }; + +INIS sinit[]= + { + {"VMODE",INI_INT}, + {"ZOOM_SPEED",INI_INT}, + {"TURN_SPEED",INI_INT}, + {"MUSIC_VOLUME",INI_INT}, + {"SOUND_VOLUME",INI_INT}, + {"SOUND_DEVICE",INI_TEXT}, + {"SOUND_MIXFREQ",INI_INT}, + {"DEFAULT_MAP",INI_TEXT}, + {"GAME_SPEED",INI_INT}, + {"PRELOAD",INI_INT}, + {"INSTALL",INI_TEXT}, + {"PATCH",INI_INT}, + {"SKIP_INTRO",INI_INT}, + {"AUTOSAVE",INI_INT}, + {"DEBUG",INI_INT}, + {"FULLRESVIDEO",INI_INT}, + {"PATCH_FILE",INI_TEXT}, + {"TITLES",INI_INT}, + {"CHAR_MIN",INI_INT}, + {"CHAR_MAX",INI_INT}, + {"EXTRAS",INI_INT}, + {"WINDOWED", INI_INT}, + {"BATTLE_ACCEL",INI_INT}, + {"WINDOWEDZOOM", INI_INT}, + {"MONITOR",INI_INT}, + {"VERSION",INI_INT}, + {"REFRESHRATE",INI_INT}, + {"CESTA_DATA",INI_TEXT}, + {"CESTA_GRAFIKA",INI_TEXT}, + {"CESTA_ZVUKY",INI_TEXT}, + {"CESTA_FONTY",INI_TEXT}, + {"CESTA_MAPY",INI_TEXT}, + {"CESTA_MUSIC",INI_TEXT}, + {"CESTA_TEMPY",INI_TEXT}, + {"CESTA_BGRAFIKA",INI_TEXT}, + {"CESTA_ITEMY",INI_TEXT}, + {"CESTA_ENEMY",INI_TEXT}, + {"CESTA_VIDEO",INI_TEXT}, + {"CESTA_DIALOGY",INI_TEXT}, + {"CESTA_POZICE",INI_TEXT}, + {"CESTA_HLAVNI",INI_TEXT}, + {"CESTA_CD",INI_TEXT}, + {"CESTA_MAPY2",INI_TEXT}, + {"CESTA_PLUGINS",INI_TEXT}, + {"CESTA_ORIG_MUSIC",INI_TEXT} + }; + + +#define CESTY_POS 27 +int last_ms_cursor=-1; +int vmode=2; + +int set_video(int mode) + { + int er=0; + + report_mode(1); + er=initmode_dx(windowed,windowedzoom,monitor,refresh); +/* + switch(mode) + { + case 1:er=initmode256(cur_xlat); + if (banking) report_mode(5); else report_mode(2); + SEND_LOG("(GAME) Video changed to 256 colors %s",banking?"Bank":"LFB",0); + break; + case 2:er=initmode32(); + if (banking) report_mode(4); else report_mode(1); + SEND_LOG("(GAME) Video changed to HIcolor %s",banking?"Bank":"LFB",0); + break; + case 0:er=initmode_lo(cur_xlat); + report_mode(3); + SEND_LOG("(GAME) Video changed to 256 VGA comp. ",0,0); + break; + case 3: free(cur_xlat);cur_xlat=create_blw_palette16(); + er=initmode16(cur_xlat); + SEND_LOG("(GAME) Video changed to 16 grayscale",0,0); + report_mode(3); + break; + case 4:er=init_empty_mode(); + report_mode(3); + SEND_LOG("(GAME) Video changed to ",0,0); + break; + case 5:free(cur_xlat);cur_xlat=create_hixlat(); + er=initmode64(cur_xlat); + if (banking) report_mode(7); else report_mode(6); + SEND_LOG("(GAME) Video changed to HIcolor64 %s",banking?"Bank":"LFB",0); + break; + + default:er=-1; + }*/ + screen_buffer_size=scr_linelen*480; + return er; + } + +int ask_video() + { + int c; + printf("\nJaky videomode?:\n" + " 1) 640x480x256 \n" + " 2) 640x480xHiColor \n"); + c=_bios_keybrd(_KEYBRD_READ)>>8; + if (c==1) exit(0); + return c-1; + } + +void pcx_fade_decomp(void **p,long *s) + { + char *buff; + load_pcx(*p,*s,A_FADE_PAL,&buff,mglob.fade_r,mglob.fade_g,mglob.fade_b); + *s=_msize(buff); + free(*p); + *p=buff; + } + +void pcx_15bit_decomp(void **p,long *s) + { + char *buff; + load_pcx(*p,*s,A_16BIT,&buff); + *s=_msize(buff); + free(*p); + *p=buff; + } + +void pcx_15bit_autofade(void **p,long *s) + { + char *buff; + load_pcx(*p,*s,A_16BIT,&buff); + *s=_msize(buff); + free(*p); + *p=buff; + buff[5]=0x80; + } + +void pcx_15bit_backgrnd(void **p,long *s) + { + char *buff; + long i;long *z; + + if (*p!=NULL) + { + load_pcx(*p,*s,A_16BIT,&buff); + z=(long *)buff; + *s=_msize(buff); + for(i=*s;i>0;i-=4,z++) *z|=0x80008000; + free(*p); + *p=buff; + } + } + +void pcx_8bit_nopal(void **p,long *s) + { + char *buff; + + if (*p!=NULL) + { + load_pcx(*p,*s,A_8BIT_NOPAL,&buff); + *s=_msize(buff); + free(*p); + *p=buff; + } + } + + +void pcx_8bit_decomp(void **p,long *s) + { + char *buff; + load_pcx(*p,*s,A_8BIT,&buff); + *s=_msize(buff); + free(*p); + *p=buff; + } + +void hi_8bit_correct(void **p,long *s) +{ + word *ptr=(word *)*p; + int i; + if (ptr[2]==8) + { + for (i=0;i<256;i++) + { + ptr[i+3]=((ptr[i+3] & ~0x1F)+ptr[i+3]); + } + } +} + + +void set_background(void **p,long *s) + { + word *data; + word *ptr; + word *pal; + char *pic; + int counter; + + if (!bgr_handle) return; + if (bgr_distance==-1) return; + data=ablock(bgr_handle); + *s=scr_linelen2*360*2; + ptr=*p=getmem(*s); + counter=scr_linelen2*360; + pal=data+3+bgr_distance*256; + pic=(char *)data+PIC_FADE_PAL_SIZE; + do + *ptr++=pal[*pic++] | BGSWITCHBIT; + while (--counter); + } + +void mouse_set_cursor(int cursor) + { + static short *ms_item=NULL; + + if (cursor==last_ms_cursor) return; + if (last_ms_cursor>0) aunlock(last_ms_cursor); + if (cursor>0) + { + alock(cursor); + schovej_mysku(); + register_ms_cursor(ablock(cursor)); + last_ms_cursor=cursor; + set_ms_finger(0,0); + ukaz_mysku(); + } + else + { + char *p; + + cursor=-cursor; + if (ms_item==NULL) ms_item=(short *)getmem(IT_ICONE_SIZE); + p=(char *)ablock(cursor/18+ikon_libs); + memcpy(ms_item,&p[(cursor%18)*IT_ICONE_SIZE],IT_ICONE_SIZE); + schovej_mysku(); + register_ms_cursor(ms_item); + set_ms_finger(45/2,55/2); + last_ms_cursor=-cursor; + ukaz_mysku(); + } + } + +void mouse_set_default(int cursor) + { + default_ms_cursor=cursor; + mouse_set_cursor(cursor); + } + +void set_font(int font,int c1,...) + { + static int last_font=-1; + int i; + + if (last_font!=-1 && last_font!=font) + { + aunlock(last_font); + alock(font); + } + curfont=ablock(font); + if (c1>=0) + if (c1 & BGSWITCHBIT) + { + charcolors[0]=0xFFFF; + for (i=1;i<5;i++) charcolors[i]=c1 & ~0x20; + } + else + { + charcolors[0]=0; + for (i=1;i<5;i++) charcolors[i]=c1 & ~0x20; + } + else if (c1==-2) + { + int *p; + + p=&c1;p++; + for (i=0;i<5;i++) charcolors[i]=*p++; + } + last_font=font; + default_font=curfont; + memcpy(f_default,charcolors,sizeof(charcolors)); + } + +void music_init() + { + char *path; +/* if (sound_detection) + { + SEND_LOG("(SOUND) SOUND_DETECT Detecting sound card",0,0); + if (sound_detect(&snd_devnum,&snd_parm1,&snd_parm2,&snd_parm3)) snd_devnum=DEV_NOSOUND; + }*/ + SEND_LOG("(SOUND) SOUND_SET Setting Sound: Device '%s' Port: %3X",device_name(snd_devnum),snd_parm1); + SEND_LOG("(SOUND) SOUND_SET Setting Sound: IRQ: %X DMA: %X",snd_parm2,snd_parm3); + set_mixing_device(snd_devnum,snd_mixing,snd_parm1,snd_parm2,snd_parm3); + SEND_LOG("(SOUND) SOUND_INIT Starting mixing",0,0); + start_mixing(); + set_snd_effect(SND_GFX,init_gfx_vol); + set_snd_effect(SND_MUSIC,init_music_vol); + path=plugins_path; + if (path==0 || path[0]==0) + path=AutodetectWinAmp(); + if (path!=0 && path[0]!=0) + { + SEND_LOG("(SOUND) Installing plugins, path: %s",path,0); + init_winamp_plugins(path); + if (path!=plugins_path) free(path); + } + SEND_LOG("(SOUND) SOUND_DONE Sound Engine should work now",0,0); + + } + +void clrscr() + { + + } + + + + +void purge_temps(char z) + { + HANDLE rc; + WIN32_FIND_DATA fi; + char c[200]; + + + strcpy(c,SWAPPATH); + strcat(c,"*.TMP"); + rc=FindFirstFile(c,&fi); + if (rc!=INVALID_HANDLE_VALUE) + do + { + strcpy(c,SWAPPATH); + strcat(c,fi.cFileName); + if (fi.cFileName[0]!='~') + { + SEND_LOG("(PURGE) Purging temp '%s'",c,0); + remove(c); + } + } + while (FindNextFile(rc,&fi)); + FindClose(rc); + + if (z) + { + strcpy(c,SWAPPATH); + strcat(c,TEMP_FILE); + SEND_LOG("(PURGE) Purging temp '%s'",c,0); + remove(c); + } + + } + + + +void back_music() + { + mix_back_sound(0); + } + +/*void *anim_idle(EVENT_MSG *msg,void **usr) + { + usr; + if (msg->msg==E_TIMER) calc_animations(); + return &anim_idle; + }*/ + +/*void timer_error() + { + puts("\x7"); + } +*/ +void *timming(EVENT_MSG *msg,void **data) + { + THE_TIMER *p,*q; + int i,j; + + data; + if (msg->msg==E_INIT) return &timming; + *otevri_zavoru=1; + j=*(int *)msg->data; + for (i=0;inext; + while (q!=NULL) + { + p=q->next; +// if (p!=NULL && p->zero!=0) timer_error(); + if (!(--q->counter)) + if (q->zavora && i==(j-1)) + { + q->zavora=0; + if (q->calls!=-2) q->proc(q); + p=q->next; + q->zavora=1; + q->counter=q->count_max; + if (q->calls!=-1) + if (--q->calls<1) + { + for(p=&timer_tree;p->next!=q;p=p->next); + p->next=q->next; + #ifdef LOGFILE + if (q->next==NULL) + SEND_LOG("(TIMER) Self remove for timer id: %d, next->",q->id,0); + else + SEND_LOG("(TIMER) Self remove for timer id: %d, next->%d",q->id,q->next->id); + #endif + free(q); + q=p; + } + //else + // q->counter=1; + } + else + q->counter=1; + if (q->next!=p && q!=p) + { + THE_TIMER *z; + SEND_LOG("(TIMER) Timer integrity corrupted",0,0); + z=&timer_tree;while(z->next!=p && z->next!=NULL) z=z->next; + if (z->next==NULL) return NULL; + } + q=p; + } + } + return NULL; + } + +void delete_from_timer(int id) + { + THE_TIMER *p,*q; + + p=&timer_tree; + q=p->next; + while (q!=NULL) + { + if (q->id==id) + { + if (q->zavora) + { + #ifdef LOGFILE + if (q->next==NULL) + SEND_LOG("(TIMER) Removing timer id: %d, next->",id,0); + else + SEND_LOG("(TIMER) Removing timer id: %d, next->%d",id,q->next->id); + #endif + p->next=q->next; + free(q); + q=p; + } + else + { + SEND_LOG("(TIMER) Can't remove timer! id: %d. Currently in use.",id,0); + q->calls=-2; + q->counter=1; + } + } + p=q;q=q->next; + } + } + +THE_TIMER *find_timer(int id) + { + THE_TIMER *p; + + p=timer_tree.next; + while (p!=NULL && p->id!=id) p=p->next; + return p; + } + + +void hold_timer(int id,char hld) + { + THE_TIMER *q; + + q=timer_tree.next; + while (q!=NULL && q->id!=id) q=q->next; + if (q!=NULL) q->counter=1-(hld<<1); + SEND_LOG("(TIMER) Timer hold id: %d status: %s",id,hld?"Hold":"Unhold"); + } + +THE_TIMER *add_to_timer(int id,int delay,int maxcall,void *proc) + { + THE_TIMER *q; + +// if (id==2 && marker && timer_tree.next->id==2) +// MARKER_HIT(timer_error()); + q=(THE_TIMER *)getmem(sizeof(THE_TIMER)); + q->counter=q->count_max=delay; + q->calls=maxcall; + q->proc=proc; + q->id=id; + q->next=timer_tree.next; + q->zavora=1; + q->zero=0; + timer_tree.next=q; + SEND_LOG("(TIMER) Adding to timer id: %d delay: %d",id,delay); + return q; + } + +static void kill_timer() + { + THE_TIMER *t; + + t=timer_tree.next; + while (t!=NULL) + { + THE_TIMER *p; + + p=t;t=t->next;free(p); + } + timer_tree.next=NULL; + } + +void *user_timer(EVENT_MSG *msg,void **usr) + { + int x; + static int lastvalue=0; + usr; + if (msg->msg==E_WATCH) + { + *otevri_zavoru=1; + x=get_timer_value(); + x-=lastvalue; + lastvalue+=x; + if (x) send_message(E_TIMER,x); + } + return &user_timer; + } + +void do_timer() + { + EVENT_MSG msg; + char x; + + msg.msg=E_IDLE; + otevri_zavoru=&x; + user_timer(&msg,NULL); + } + +void done_skeldal(void) + { + + SEND_LOG("(GAME) Video returned to textmode",0,0); + close_manager(); + close_story_file(); + purge_temps(1); + stop_mixing(); +// deinstall_mouse_handler(); + if (texty!=NULL) release_list(texty);texty=NULL; + if (cur_config!=NULL) release_list(cur_config);cur_config=NULL; + kill_timer(); + SEND_LOG("NORMAL TERMINATING--------------------------",0,0); + } + + +int cislovka(int i) + { + if (i==1) return 0; + if (i>1 && i<5) return 1; + return 2; + } + +void register_basic_data() + { + int i,s; + TDREGISTERS *p; + char xname[16]; + + s=sizeof(registred)/sizeof(TDREGISTERS); + p=registred; + for(i=0;ih_num,p->name,p->proc,p->path); + def_handle(H_BOTTBAR,"",bott_draw_proc,0); + for(i=0;imsg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + if (c==';') save_dump(); + } + return; + } + +void add_game_window() + { + WINDOW *p; + CTL3D *c; + + c=def_border(0,0); + p=create_window(0,0,0,0,0,c); + desktop_add_window(p); + } + + + +void error_exception(EVENT_MSG *msg,void **unused) + { + if (msg->msg==E_PRGERROR) + { + unused; + SEND_LOG("(ERROR) Runtime error detected ... Game terminator lunched.",0,0); + SEND_LOG("(ERROR) Log: Now dump of useful informations:",0,0); + SEND_LOG("(ERROR) Log: Map name '%s'",level_fname==NULL?"":level_fname,0); + SEND_LOG("(ERROR) Log: Sector %d Direction %d",viewsector,viewdir); + SEND_LOG("(ERROR) Log: Last 'memman' handle: %x",memman_handle,0); + SEND_LOG("(ERROR) Log: Battle: %d Select_player %d",battle,select_player); + closemode(); + printf("Program zp–sobil bhovou chybu a bude ukon‡en\n" + "Poslednˇ zpracov van  data mla rukojeź ‡ˇslo %xh\n",memman_handle); + printf("Map: %s Sector %d Direction %d\n",level_fname==NULL?"":level_fname,viewsector,viewdir); + printf("Nynˇ se program pokusˇ ulo‘it hru...\n\n"); + autosave_enabled=1; + autosave(); + printf("Hra byla Łsp¨n ulo‘ena pod n zvem AUTOSAVE\n"); + exit(0); + } + } + +void swap_error_exception() + { + closemode(); + SEND_LOG("(ERROR) Disk is full ...",0,0); + puts("Program jiz nema kam odkladat, protoze disk s odkladacim souborem byl \n" + "zaplnen. Uvolnete prosim nejake misto na odkladacim disku, nebo zmente \n" + "adresar odkladani na jednotku, kde je vice mista"); + puts("Vase pozice bude ulozena pod nazvem AUTOSAVE\n" + "Pokud vsak mate pozice na stejn‚m disku jako odkladaci soubor (coz je\n" + "zakladni nastaveni) bude ulozeni z 90% bohuzel neuspesne..."); + autosave_enabled=1; + autosave(); + exit(0); + } + +void *boldcz; + +#define ERR_WINX 320 +#define ERR_WINY 100 + +/* + +char device_error(int chyba,char disk,char info) + { + char c; + void *old; + + old=_STACKLOW; + _STACKLOW=NULL; + chyba,disk,info; + curfont=&boldcz; + charcolors[0]=0xffff; + for(c=1;c<5;c++) charcolors[c]=0x7fff; + memcpy(buffer_2nd,screen,screen_buffer_size); + trans_bar(320-ERR_WINX/2,240-ERR_WINY/2,ERR_WINX,ERR_WINY,0); + curcolor=0x7fff; + rectangle(320-ERR_WINX/2,240-ERR_WINY/2,320+ERR_WINX/2,240+ERR_WINY/2,0x7fff); + set_aligned_position(320,230,1,1,texty[8]);outtext(texty[8]); + set_aligned_position(320,250,1,1,texty[9]);outtext(texty[9]); + showview(0,0,0,0); + do + { + c=getche(); + } + while (c!=13 && c!=27); + memcpy(screen,buffer_2nd,screen_buffer_size); + showview(0,0,0,0); + _STACKLOW=old; + return (c==13?_ERR_RETRY:_ERR_FAIL); + } +*/ +static void patch_error(int err) + { + position(0,460); + curcolor=0;bar(0,460,640,479); + memcpy(charcolors,flat_color(RGB555(31,31,31)),sizeof(charcolors)); + curfont=boldcz; + switch(err) + { + case 0:outtext("File has been patched: ");outtext(patch_file);break; + case 1:outtext("Patch error within file: ");outtext(patch_file);break; + case 2:outtext("Cannot patch");break; + case 3:outtext("Missing or error in main data file, patching ingnored!");break; + break; + } + showview(0,460,640,20); + } + +void init_skeldal(void) + { + char c[200],d[200]; + int verr; + + boldcz=LoadDefaultFont(); +SEND_LOG("(INIT) Reading texts.",0,0); + cti_texty(); + timer_tree.next=NULL; +SEND_LOG("(INIT) Setting random seed.",0,0); + srand(clock()); +SEND_LOG("(INIT) Creating 256 color palette.",0,0); + cur_xlat=create_special_palette(); +SEND_LOG("(INIT) Init message system - event handler",0,0); + init_events(100); +SEND_LOG("(INIT) Setting videomode.",0,0); + verr=set_video(vmode); + if (verr) + { + exit(ERR_GENERAL); + } +SEND_LOG("(INIT) Initializing engine.",0,0); + general_engine_init(); + atexit(done_skeldal); +/*SEND_LOG("(INIT) Loading DOS error handler.",0,0); + install_dos_error(device_error,(char *)getmem(4096)+4096);*/ + swap_error=swap_error_exception; + sprintf(c,"%s%s",SWAPPATH,TEMP_FILE); + sprintf(d,"%s%s",pathtable[SR_DATA],"skeldal.ddl"); +SEND_LOG("(INIT) Initializing memory manager",0,0); + init_manager(d,c); +SEND_LOG("(GAME) Memory manager initialized. Using DDL: '%s' Temp dir: '%s'",d,c); + texty_knihy=find_map_path("kniha.txt"); +SEND_LOG("(INIT) Installing GUI",0,0); + install_gui(); +SEND_LOG("(INIT) Attaching patch.",0,0); + if (patch_file!=NULL) patch_error(add_patch_file(patch_file)); +SEND_LOG("(INIT) Registring basic data.",0,0); + register_basic_data(); +SEND_LOG("(INIT) Timer event handler.",0,0); + send_message(E_DONE,E_WATCH,timer); + send_message(E_DONE,E_IDLE,redraw_desktop_call); + send_message(E_ADD,E_TIMER,timming); +SEND_LOG("(INIT) User timer.",0,0); + send_message(E_ADD,E_WATCH,user_timer); +SEND_LOG("(INIT) Mouse clicking maps.",0,0); + send_message(E_ADD,E_MOUSE,ms_clicker); +SEND_LOG("(INIT) Global keyboard event handler.",0,0); + send_message(E_ADD,E_KEYBOARD,global_kbd); +SEND_LOG("(INIT) Error exception event handler.",0,0); + send_message(E_ADD,E_PRGERROR,error_exception); +SEND_LOG("(INIT) Wizard handler.",0,0); + if (debug_enabled) install_wizard(); +SEND_LOG("(INIT) Background music timer.",0,0); + add_to_timer(TM_BACK_MUSIC,5,-1,back_music); +SEND_LOG("(INIT) Creating game window.",0,0); + add_game_window(); +SEND_LOG("(INIT) Music.",0,0); + music_init(); +SEND_LOG("(INIT) Mouse interrupt handler.",0,0); + if ((verr=init_mysky())!=0) + { + closemode(); + puts(texty[174-verr]); + SEND_LOG("(ERROR) %s (%d)",texty[174-verr],verr); + SEND_LOG("(ERROR) Mouse not found, shutting down.",0,0); + exit(0); + } +SEND_LOG("(INIT) Mouse initialized.",0,0); +// hranice_mysky(0,0,639,479); +SEND_LOG("(INIT) Loading mouse cursor.",0,0); + mouse_set_default(H_MS_DEFAULT); + ukaz_mysku(); + konec_skladby=play_next_music; +SEND_LOG("(INIT) Loading spells.",0,0); + kouzla_init(); +SEND_LOG("(INIT) Loading items.",0,0); + load_items(); +SEND_LOG("(INIT) Loading shops.",0,0); + load_shops(); + SetWheelMapping('H','P'); + } + +void wire_main_functs(); +void unwire_main_functs() + { + SEND_LOG("(SYS) Wire main functions",0,0); + delete_from_timer(TM_FLY); + delete_from_timer(TM_SCENE); + delete_from_timer(TM_REGEN); + send_message(E_DONE,E_KEYBOARD,game_keyboard); + send_message(E_DONE,E_KROK,real_krok); + disable_click_map(); + cancel_render=1; + wire_proc=wire_main_functs; + } + + +void wire_main_functs() + { + SEND_LOG("(SYS) unWire main functions",0,0); + add_to_timer(TM_SCENE,gamespeed,-1,refresh_scene); + add_to_timer(TM_FLY,gamespeed,-1,calc_fly); + add_to_timer(TM_REGEN,500,-1,real_regeneration); + send_message(E_ADD,E_KEYBOARD,game_keyboard); + send_message(E_ADD,E_KROK,real_krok); + change_click_map(clk_main_view,CLK_MAIN_VIEW); + unwire_proc=unwire_main_functs; + cur_mode=MD_GAME; + running_battle=0; + recalc_volumes(viewsector,viewdir); + cancel_pass=1; + } + + +void init_game() + { + SEND_LOG("(INIT) Inventory.",0,0); + init_inventory(); + SEND_LOG("(INIT) Characters.",0,0); + reg_grafiku_postav(); + build_all_players(); + } + +void *map_keyboard(EVENT_MSG *msg,void **usr); + +char doNotLoadMapState=0; + +static reload_map_handler(EVENT_MSG *msg,void **usr) +{ +extern char running_battle; + if (msg->msg==E_RELOADMAP) + { + int i; + va_list list=msg->data; + const char *fname=va_arg(list,const char *); + int sektor=va_arg(list,int); + strncpy(loadlevel.name,fname,sizeof(loadlevel.name)); + loadlevel.start_pos=sektor; + for(i=0;i \n\n" + " jmeno mapy\n" + " Cislo startovaciho sektoru\n" + ); + exit(0); + } + +extern char nofloors; + +/* +void set_verify(char state); +#pragma aux set_verify parm [eax]=\ + "mov ah,2eh"\ + "int 21h" +*/ +void play_movie_seq(char *s,int y) + { + int hic=full_video?SMD_HICOLOR+128:SMD_HICOLOR,cc=full_video?SMD_256+128:SMD_256; + word *lbuffer=GetScreenAdr(); + set_play_attribs(lbuffer,0,banking,vmode==5); + switch (vmode) + { + case 1:if (!banking) + play_animation(s,cc,y,snd_devnum!=DEV_NOSOUND); + else + { + set_play_attribs(GetScreenAdr(),1,0,vmode==5); + play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND); + } + break; + case 5: + case 2:play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND);break; + default: set_play_attribs(GetScreenAdr(),1,0,vmode==5); + play_animation(s,hic,y,snd_devnum!=DEV_NOSOUND);break; + } + } + + +void play_anim(int anim_num) + { + char *s; + char *t,*z; + TSTR_LIST titl=NULL; + concat(s,pathtable[SR_VIDEO],texty[anim_num]); + if (snd_devnum==DEV_NOSOUND || titles_on) + { + concat(t,s," "); + z=strrchr(t,'.'); + if (z!=NULL) + { + strcpy(z,".TXT"); + if (load_string_list_ex(&titl,t)) titl=NULL; + } + else titl=NULL; + } + else titl=NULL; + set_title_list(titl);set_font(H_FBIG,RGB(200,200,200)); + curcolor=0;bar(0,0,639,459); + showview(0,0,0,0); + play_movie_seq(s,60); + set_title_list(NULL);if (titl!=NULL) release_list(titl); + } + + +/*main(int argc,char *argv[]) + { + int err;int sect;int dir=0; + + //if (argc<2) help(); + + dir; + set_verify(0); + mman_pathlist=&pathtable; + //nofloors=1; + zoom_speed(1); + turn_speed(1); + configure("skeldal.ini",config_skeldal); + purge_temps(1); + textmode_effekt(); + clrscr(); + init_skeldal(); + enter_menu(); + if (argc<2) + { + invex_anim(); + // send_message(E_ADD,E_MOUSE,waiter); + // send_message(E_ADD,E_KEYBOARD,waiter); + // add_to_timer(TM_WAITER,1,-1,timer_waiter); + strncpy(loadlevel.name,default_map,12); + } + else strncpy(loadlevel.name,argv[1],12); + err=load_map(loadlevel.name); + if (argc>=3) sscanf(argv[2],"%d",§); + else + { + sect=mglob.start_sector; + dir=mglob.direction; + } + loadlevel.start_pos=sect; + loadlevel.dir=dir; + init_game(); + while (loadlevel.name[0]) + { + if (err) + { + closemode(); + switch (err) + { + case -1: printf("Error while loading map....file not found\n");break; + case -2: printf("Missing -1 at the end of map string table");break; + case -3: printf("Map file is corrupted!\n");break; + default: printf("Error in string table at line %d",err);break; + } + exit(1); + } + viewsector=loadlevel.start_pos; + viewdir=loadlevel.dir; + loadlevel.name[0]=0; + enter_game(); + leave_current_map(); + if (loadlevel.name[0]!=0)err=load_map(loadlevel.name); + } + closemode(); + } + +*/ + +#define V_NOVA_HRA 0 +#define V_OBNOVA_HRY 1 +#define V_UVOD 2 +#define V_AUTORI 3 +#define V_KONEC 4 + +#define H_ETOPBAR (H_MENUS_FREE+100) +#define H_EDESK (H_MENUS_FREE+101) +static void game_big_circle(char enforced) + { + int err; + int r; + char s[13]; + SEND_LOG("\n(GAME) --------- Entering big loop ------------",0,0); + purge_playlist(); + s[12]=0;strncpy(s,loadlevel.name,12); + err=load_map(s); + if (!enforced) + { + loadlevel.start_pos=mglob.start_sector; + loadlevel.dir=mglob.direction; + } + while (loadlevel.name[0]) + { + if (err) + { + char buff[256]; + closemode(); + switch (err) + { + case -1: sprintf(buff,"Error while loading map (%s) ....file not found\n",s);break; + case -2: sprintf(buff,"Missing -1 at the end of map string table");break; + case -3: sprintf(buff,"Map file is corrupted!\n");break; + default: sprintf(buff,"Error in string table at line %d",err);break; + } + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONSTOP); + exit(1); + } + viewsector=loadlevel.start_pos; + viewdir=loadlevel.dir; + if (viewsector==0) + { + viewsector=set_leaving_place(); + if (viewsector==0) + { + viewsector=mglob.start_sector; + viewdir=mglob.direction; + } + else + { + int i; + viewdir=0; + for (i=0;i<4;i++) if (~map_sides[i+(viewsector<<2)].flags & (SD_PLAY_IMPS | SD_PRIM_VIS)) + {viewdir=i;break;} + } + } + for(r=0;r2) + { + sscanf(argv[2],"%d",§); + enforce=1; + dir=0; + } + loadlevel.start_pos=sect; + loadlevel.dir=dir; + init_game(); + if (argc>=2) + { + memcpy(postavy,postavy_2,sizeof(THUMAN)*6); + memset(runes,0x7f,sizeof(runes)); + } + reg_grafiku_postav(); + memset(GlobEventList,0,sizeof(GlobEventList)); + game_big_circle(enforce); + } + +static void undef_menu() + { + int i; + for(i=0;i<255;i++) undef_handle(0x8000+i); + } + + +static EVENT_PROC(load_error_report) + { + user_ptr; + WHEN_MSG(E_IDLE) + { + message(1,0,0,"",texty[79],texty[80]); + exit_wait=0; + send_message(E_CLOSE_MAP); + } + } + +static void wire_load_saved() + { + send_message(E_CLOSE_MAP,-1); + } + +static void load_saved_game(void) + { + signed char game; + + err: + loadlevel.name[0]=0; + def_handle(H_ETOPBAR,"topbar_e.pcx",pcx_15bit_decomp,SR_BGRAFIKA); + schovej_mysku();wire_proc=wire_load_saved; + put_picture(0,0,ablock(H_ETOPBAR)); + put_picture(0,378,ablock(H_DESK)); + wire_save_load(4); + ukaz_mysku(); + update_mysky(); + game=*((char *)task_wait_event(E_CLOSE_MAP)); + unwire_proc(); + disable_click_map(); + task_wait_event(E_TIMER); + if (game!=-1) + { + reinit_kouzla_full(); + open_story_file(); + memset(GlobEventList,0,sizeof(GlobEventList)); + if (load_game(game)) + { + send_message(E_ADD,E_IDLE,load_error_report); + task_wait_event(E_CLOSE_MAP); + send_message(E_DONE,E_IDLE,load_error_report); + exit_wait=0; + goto err; + } + pick_set_cursor(); + undef_menu(); + init_game(); + build_all_players(); + game_big_circle(1); + exit_wait=1; + } + } + +static void start(va_list args) + { + int volba; + char /*d,*/openning; + + zde: + openning=0; + update_mysky(); + schovej_mysku(); + if (!skip_intro) + { + show_jrc_logo("LOGO.PCX"); + play_anim(7); + } + skip_intro=0; + create_playlist(texty[1]); + //play_next_music(&d); + change_music(NULL); + zobraz_mysku(); + showview(0,0,0,0); + do + { + volba=enter_menu(openning);openning=1; + switch (volba) + { + case V_KONEC:exit_wait=1;break; + case V_NOVA_HRA: if (!enter_generator()) + { + undef_menu(); + new_game(0,NULL); + exit_wait=1; + } + break; + case V_UVOD:bar(0,0,639,479);goto zde;break; + case V_OBNOVA_HRY:load_saved_game();break; + case V_AUTORI:run_titles(NULL);break; + } + } + while (!exit_wait); + } + +static void start_from_mapedit(va_list args) +//#pragma aux start_from_mapedit parm[] + { + int argc=va_arg(args,int); + char **argv=va_arg(args,char **); + new_game(argc-1,argv+1); + exit_wait=1; + } + +void disable_intro() + { + add_field_num(&cur_config,sinit[12].heslo,1); + update_config(); + } + +#include "crashdump.h" + +void main(int argc,char *argv[]) + { + char *c,rm; + + InitCrashDump(); + + if (argc>=3) rm=!strcmp(argv[1],"12345678");else rm=0; + if (!rm) if (OtevriUvodniOkno()==0) return; + + //OPEN_LOG("syslog"); + OPEN_LOG("con"); + SEND_LOG("START --------------------------",0,0); + argv; + c=getcwd(NULL,_MAX_PATH+1); + pathtable[SR_SAVES]=getmem(strlen(c)+2); + strcpy(pathtable[SR_SAVES],c); + strcat(pathtable[SR_SAVES],"\\"); + free(c); + SEND_LOG("(GAME) Save directory sets to '%s'",pathtable[SR_SAVES],0); +// set_verify(0); + mman_pathlist=pathtable; + zoom_speed(1); + turn_speed(1); + SetEnvironmentVariable("BSVER",VERSION); + configure(CONFIG_NAME); + if ((argc>=2 || SelectAdventure()) && !rm ) + { + char *adventure; + char **config=cur_config; + + const char *music = mman_pathlist[SR_MUSIC]; + mman_pathlist[SR_ORGMUSIC]=(char *)getmem(strlen(music)+1); + strcpy(mman_pathlist[SR_ORGMUSIC],music); + + if (argc<2) adventure=GetSelectedAdventure(); + else adventure=argv[1]; + cur_config=NULL; + SEND_LOG("(GAME) Starting new adventure: %s",adventure,0); + configure(adventure); + release_list(cur_config); + cur_config=config; + } +#ifdef LOGFILE + { + int i; + for(i=0;i<(sizeof(pathtable)/4);i++) SEND_LOG("(GAME) LOG: Using directory '%s' as '%s'",pathtable[i],sinit[i+CESTY_POS].heslo); + } +#endif + start_check(); + purge_temps(1); +// textmode_effekt(); + clrscr(); + SEND_LOG("\n(GAME) Init----------------",0,0); + init_skeldal(); + + //add_task(32768,check_number_1phase,argv[0]); + SEND_LOG("(INIT) Starting game thread.",0,0); + if (argc>=3 && rm) + { + add_task(65536,start_from_mapedit,argc,argv); + } + else + add_task(65536,start); + SEND_LOG("(INIT) Main thread goes to sleep.",0,0); +/* position(200,200); + set_font(H_FBIG,RGB(200,200,200)); + outtext("Ahoj lidi"); + showview(0,0,0,0);*/ + escape(); + update_config(); + closemode(); + } + +int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) + { + main(__argc, __argv); + } + +#include "..\game\version.h" + + +int GetExeVersion() + { + return VERSIONNUM; + } \ No newline at end of file diff --git a/GAME/SNDandMUS.C b/GAME/SNDandMUS.C new file mode 100644 index 0000000..b21c015 --- /dev/null +++ b/GAME/SNDandMUS.C @@ -0,0 +1,644 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#include +//#include //Sound and Nosound +#include +#include + +#define PL_RANDOM 1 +#define PL_FORWARD 2 +#define PL_FIRST 3 + +#define CHANNELS 20 +#define TRACKS 512 + +#define SND_EFF_MAXVOL 32000 +#define SND_EFF_DESCENT 8000 + +#define have_loop(x) ((x)->start_loop!=(x)->end_loop) + +typedef unsigned short SND_FIND_TABLE[2]; +typedef struct snd_info + { + TMA_SOUND *data; //4 + short xpos,ypos,side; //10 + word volume,block; //14 + }SND_INFO; + +static short chan_state[CHANNELS]; +static short track_state[TRACKS]; +static short sample_volume=255; + +//static struct t_wave wav_last_head; +//static int wav_last_size; +static int mute_task=-1; +static char sound_enabled=1; + +SND_INFO tracks[TRACKS]; +SND_INFO playings[CHANNELS]; +static word locks[32]; + +TSTR_LIST cur_playlist=NULL; +TSTR_LIST sound_table=NULL; +int playlist_size; +int playing_track=0; +int remain_play=0; +int play_list_mode=PL_RANDOM; + +void init_tracks() + { + memset(tracks,0,sizeof(tracks)); + memset(playings,0,sizeof(playings)); + memset(chan_state,0xff,sizeof(chan_state)); + memset(track_state,0xff,sizeof(track_state)); + memset(locks,0,sizeof(locks)); + } + +static char last_beep_lev; + +/*void pcspeak_uroven(char value,int time); +#pragma aux pcspeak_uroven parm[bh][ecx]=\ + "mov ah,last_beep_lev"\ + "lp2:add ah,bh"\ + "mov al,48h"\ + "jc lp1"\ + "mov al,4ah"\ + "lp1:out 61h,al"\ + "loop lp2"\ + "mov last_beep_lev,ah"\ + modify [eax] + + +static int get_pc_speed() + { + int ticks=0; + int timer=get_timer_value(); + while (get_timer_value()-timer<50) pcspeak_uroven(127,1000),ticks+=1000; + return ticks; + } + +void pc_speak_play_sample(char *sample,int size,char step,int freq) + { + static speed=0; + int ticker; + if (!speed) speed=get_pc_speed(); + _disable(); + ticker=speed/freq; + sample+=step/2; + while (size>0) + { + if (step==2) + pcspeak_uroven(*sample ^ 0x80,ticker); + else + pcspeak_uroven(*sample,ticker); + sample+=step; + size-=step; + } + _enable(); + nosound(); + } + +*/ + +int find_free_channel(int stamp) + { + int i,j; + int minvol,left,right,mid; + + j=0; + if (stamp) for(i=0;i=0)-(side==3)*(*x<=0); + *y+=(side==2)*(*y>=0)-(side==0)*(*y<=0); + ds=abs(*x)+abs(*y); + ds=SND_EFF_MAXVOL-(SND_EFF_DESCENT*8*ds)/(8+ds); + return ds; + } + +int calcul_volume(int chan,int x,int y,int side,int volume) + { + int lv,rv; + int ds,bal,i; + + if (side==-1) side=viewdir; + side&=3; + ds=calc_volume(&x,&y,side); + if (ds<=0) + { + release_channel(chan); + return -1; + } + for(i=0;iy) + if (x>0) bal=100-y*50/x;else bal=-100-y*50/x; + else bal=50*x/y; + ds=ds*volume/100; + if (bal<0) + { + lv=ds*(100+bal)/100;rv=ds; + } + else + { + rv=ds*(100-bal)/100;lv=ds; + } + lv=(lv*sample_volume)>>8; + rv=(rv*sample_volume)>>8; + set_channel_volume(chan,lv,rv); + return 0; + } + +void wav_load(void **p,long *s) + { + char *sr; + long *d; + char *c; + char *tg; + void *tgr; + size_t siz; + struct t_wave x[3]; + + sr=*p; + sr=find_chunk(sr,WAV_FMT); + read_chunk(sr,&x); + sr=*p; + sr=find_chunk(sr,WAV_DATA); + *s=get_chunk_size(sr); + tgr=tg=getmem(*s+sizeof(struct t_wave)+4); + memcpy(tgr,x,sizeof(struct t_wave)); + tg+=sizeof(struct t_wave); + *(int *)tg=*s; + tg+=4; + read_chunk(sr,tg); + free(*p); + *p=tgr; + siz=*s; + *s+=sizeof(struct t_wave)+4; +/* if (x[0].freq!=x[0].bps) + { + char s; + + siz>>=1; + s=siz & 1; + siz>>=1; + d=tg; + for(;siz--;d++) *d^=0x80008000; + if (s) {c=(char *)d;c[1]^=0x80;} + } + else + { + char s; + + s=siz & 3; + siz>>=2; + d=(long *)tg; + for(;siz--;d++) *d^=0x80808080; + c=(char *)d; + for(;s--;c++) *c^=0x80; + }*/ + } + +void play_effekt(int x,int y,int xd,int yd,int side,int sided,TMA_SOUND *p) + { + int chan; + int blockid; + SND_INFO *track; + THANDLE_DATA *z; + char *s; + + if (!sound_enabled) return; + side; + chan=find_free_channel(p->soundid); + release_channel(chan); + track=&tracks[p->soundid]; + track->data=p; + track->xpos=xd; + track->ypos=yd; + track->side=sided; + track_state[p->soundid]=-1; + if (p->bit16 & 0x8) + { + int vol=SND_EFF_MAXVOL*p->volume/100; + if (rnd(100)>50) set_channel_volume(chan,rnd(vol),vol); + else set_channel_volume(chan,vol,rnd(vol)); + } + else + if (calcul_volume(chan,x-xd,y-yd,/*side-*/sided,p->volume)) return; + if (p->filename[0]==1) memcpy(&blockid,&p->filename[1],4); + else + { + blockid=find_handle(p->filename,wav_load); + if (blockid==-1) + { + z=def_handle(end_ptr,p->filename,wav_load,SR_ZVUKY); + blockid=end_ptr++; + if (level_preload) apreload(blockid); + } + memcpy(&p->filename[1],&blockid,4); + p->filename[0]=1; + } + alock(blockid); + s=ablock(blockid); + s+=p->offset+sizeof(struct t_wave)+4; + play_sample(chan,s,p->end_loop-p->offset,p->start_loop-p->offset,p->freq,1+(p->bit16 & 1)); + playings[chan].data=p; + playings[chan].xpos=xd; + playings[chan].ypos=yd; + playings[chan].side=sided; + playings[chan].volume=p->volume; + playings[chan].block=blockid; + chan_state[chan]=p->soundid; + track_state[p->soundid]=chan; + } + +void restore_sound_name(TMA_SOUND *p) + { + int blockid; + THANDLE_DATA *h; + + if (p->filename[0]==1) + { + memcpy(&blockid,&p->filename[1],4); + do + { + h=get_handle(blockid); + if (h->status==BK_SAME_AS) blockid=h->seekpos;else blockid=-1; + } + while (blockid!=-1); + strncpy(p->filename,h->src_file,12); + } + } + +void restore_sound_names() + { + int i; + + for(i=0;igeneral.action==MA_SOUND) restore_sound_name(&z->sound); + r=(int *)((char *)r+mcsiz); + } + } + } + +void recalc_volumes(int sector,int side) + { + int i; + int newx,newy,layer; + + if (sector>=mapsize) return; + + side; + SEND_LOG("(SOUND) %s","Recalculating volumes",0); + newx=map_coord[sector].x; + newy=map_coord[sector].y; + layer=map_coord[sector].layer; + for(i=0;i=0 && playings[i].side>=0) + { + calcul_volume(i,newx-playings[i].xpos,newy-playings[i].ypos,/*side-*/playings[i].side,playings[i].volume); + if (!get_channel_state(i)) release_channel(i); + } + else calcul_volume(i,0,0,-1,playings[i].volume); + for(i=1;i0) + if (have_loop(tracks[i].data))play_effekt(newx,newy,tracks[i].xpos,tracks[i].ypos,side,tracks[i].side,tracks[i].data); + } + } + mute_task=-1; + } + +void create_playlist(char *playlist) + { + char *c; + char mode[20]; + char shift; + int i=1,j; + if (cur_playlist!=NULL) release_list(cur_playlist); + cur_playlist=NULL; + if (playlist==NULL) return; + if (playlist=="") return; + c=playlist; + while (*c && *c==32) c++; + sscanf(c,"%s",mode); + strupr(mode); + shift=1; + if (!strcmp(mode,"RANDOM")) play_list_mode=PL_RANDOM; + else if (!strcmp(mode,"FORWARD")) play_list_mode=PL_FORWARD; + else if (!strcmp(mode,"FIRST")) play_list_mode=PL_FIRST; + else shift=0; + if (shift) c+=strlen(mode);else play_list_mode=PL_RANDOM; + while (*c && *c==32) c++; + playlist=c; + if (playlist=="") return; + for (c=playlist;c!=NULL;c=strchr(c+1,' ')) i++; + playlist_size=i-1; + cur_playlist=create_list(i); + j=0; + for (c=playlist;c!=NULL;c=strchr(c+1,' ')) + { + char *e; + char d[MAX_PATH+2]="!"; + strncat(d,c+j,MAX_PATH);d[MAX_PATH+1]=0;j=1; + if ((e=strchr(d,32))!=NULL) *e=0; + str_add(&cur_playlist,d); + } + if (play_list_mode==PL_FIRST) + { + cur_playlist[0][0]=32; + remain_play=1; + play_list_mode=PL_RANDOM; + } + else + { + remain_play=0; + } + playing_track=-1; + } + +void play_next_music(char **c) + { + int i,step; + static char d[MAX_PATH]; + + *c=NULL; + if (cur_playlist==NULL) return; + if (!remain_play) + for(i=0;cur_playlist[i]!=NULL;remain_play++,i++) cur_playlist[i][0]=32; + if (play_list_mode==PL_RANDOM) + step=rand()*(playlist_size-1)/32768+1; + else + step=1; + i=playing_track; + do + { + i++; + if (cur_playlist[i]==NULL) i=0; + if (cur_playlist[i][0]==32) step--; + } + while (step); + playing_track=i; + sprintf_s(d,sizeof(d),"%s%s",pathtable[SR_MUSIC],cur_playlist[i]+1); + if (_access(d,0) == -1) + sprintf_s(d,sizeof(d),"%s%s",pathtable[SR_ORGMUSIC],cur_playlist[i]+1); + cur_playlist[i][0]=33; + remain_play--; + *c=d; + } + +void purge_playlist() + { + if (cur_playlist!=NULL)release_list(cur_playlist); + cur_playlist=NULL; + } + +void play_sample_at_sector(int sample,int sector1,int sector2,int track, char loop) + { + int x,y,xd,yd,chan; + char *s; + struct t_wave *p; + int siz; + int oldtrack; + + if (!sound_enabled) return; + if (map_coord[sector1].layer!=map_coord[sector2].layer) return; + x=map_coord[sector1].x; + y=map_coord[sector1].y; + xd=map_coord[sector2].x; + yd=map_coord[sector2].y; + chan=find_free_channel(track); + oldtrack=track_state[track]; + if (!track || oldtrack==-1) release_channel(chan); + if (calcul_volume(chan,x-xd,y-yd,viewdir,100)) return; + if (!track || oldtrack==-1) + { + alock(sample); + s=ablock(sample); + p=(struct t_wave *)s; + s+=sizeof(struct t_wave); + siz=*(int *)s;s+=4; + play_sample(chan,s,siz,loop?0:siz,p->freq,(p->freq!=p->bps?2:1)); + playings[chan].data=NULL; + } + playings[chan].xpos=xd; + playings[chan].ypos=yd; + playings[chan].side=viewdir; + playings[chan].volume=100; + playings[chan].block=sample; + chan_state[chan]=track; + track_state[track]=chan; + } + +void play_sample_at_channel(int sample,int channel,int vol) + { + char *s; + struct t_wave *p; + int siz; + + if (!sound_enabled) return; + channel+=CHANNELS; + vol*=SND_EFF_MAXVOL/100; + set_channel_volume(channel,vol,vol); + if (locks[channel]) aunlock(locks[channel]); + alock(sample); + locks[channel]=sample; + s=ablock(sample); + p=(struct t_wave *)s; + s+=sizeof(struct t_wave); + siz=*(int *)s;s+=4; + play_sample(channel,s,siz,siz,p->freq,(p->freq!=p->bps?2:1)); + } + + +void create_sound_table(char *template,long size) + { + char *c,*s; + int i=0; + + if (sound_table==NULL) sound_table=create_list(2); + s=c=template; + while (c-s +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" + +#define PRG_COLOR RGB555(0,31,31) +#define PRG_HELP_COLOR RGB555(31,31,0) + +TMOB *attack_mob; +short init_distance; +short init_sector; +short select_player=-1; +char running_battle=0; +char att_player; +char pgm_help; +char death_play;char far_play; +short cislo_potvory; +short cislo_kola; +HUM_ACTION spell_string; +short caster; +short vybrana_zbran=-1; +char plr_switcher[POCET_POSTAV]; +static autostart_round=0; + +char autoattack=0; +char immortality=0; +long level_map[]= + {400, //level 2 + 1000, // 3 + 1800, // 4 + 2800, // 5 + 5000, // 6 + 8400, // 7 + 13000, // 8 + 20000, // 9 + 30000, // 10 + 45000, // 11 + 70000, // 12 + 110000, // 13 + 180000, // 14 + 300000, // 15 + 500000, // 16 + 800000, // 17 + 1300000, // 18 + 2000000, // 19 + 3000000, // 20 + 4500000, // 21 + 6500000, // 22 + 10000000, // 23 + 11000000, // 24 + 13000000, // 25 + 16000000, // 26 + 20000000, // 27 + 25000000, // 28 + 32000000, // 29 + 40000000, // 30 + 50000000, // 31 + 60000000, // 32 + 70000000, // 33 + 80000000, // 34 + 90000000, // 35 + 100000000, // 36 + 110000000, // 37 + 120000000, // 38 + 130000000, // 39 + 140000000, // 40 + 0x7fffffff // Immortal! + }; + +#define MAX_WEAPON_SKILL 10 + +word weapon_skill[]= //tabulka poctu uspesnych zasahu pro kazdy level + { + 20, //level 1 + 40, // 2 + 80, // 3 + 160, // 4 + 320, // 5 + 640, // 6 + 1280, // 7 + 2560, // 8 + 5120, // 9 + 10240, // 10 + 65535, // max + }; + +char JePozdrzeno(); +char mask_click(int id,int xa,int ya,int xr,int yr); +char mask_click_help(int id,int xa,int ya,int xr,int yr); +char mask_click_help_clear(int id,int xa,int ya,int xr,int yr); +char souboje_clk_throw(int id,int xa,int ya,int xr,int yr); +char runes_mask(int id,int xa,int ya,int xr,int yr); +char cancel_runes(int id,int xa,int ya,int xr,int yr); +char power(int id,int xa,int ya,int xr,int yr); +char cancel_power(int id,int xa,int ya,int xr,int yr); +char ask_who_proc(int id,int xa,int ya,int xr,int yr); +void wire_programming(); +void souboje_vybrano(int d); +void program_draw(); + +void (*after_spell_wire)(); + +short *poradi=NULL; +short *prave_hraje; + +void wire_programming(); +void unwire_programming(); +void wire_jadro_souboje(); +void unwire_jadro_souboje(); + +char sel_zivel=0; +static char prekvapeni=0; +char powers[3]={0,1,2}; +HUM_ACTION *magic_data; + +static int minwait=0,maxwait=-1; + +#define CLK_SOUBOJE 15 +T_CLK_MAP clk_souboje[]= + { + {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {1,147,0,205,14,clk_saveload,2,H_MS_DEFAULT}, + {0,207,0,265,14,clk_saveload,2,H_MS_DEFAULT}, + {-1,291,0,313,14,go_book,2,H_MS_DEFAULT}, + {-1,528,378,630,479,mask_click,2,-1}, + {1,320,303,639,376,pick_item_,2,-1},//344 + {0,0,303,320,376,pick_item_,2,-1},//344 + {3,0,200,320,340,pick_item_,2,-1},//303 + {2,320,200,639,340,pick_item_,2,-1},//303 + {-1,528,378,630,479,mask_click_help,1,-1}, + {-1,0,0,640,480,mask_click_help_clear,1,-1}, + {MS_GAME_WIN,0,17,639,377,souboje_clk_throw,2,-1}, + {-1,54,378,497,479,start_invetory,2+8,-1}, + }; + + +char clk_enter(int id,int xa,int ya,int xr,int yr) + { + int i=28*256; + id;xa;ya;xr;yr; + send_message(E_KEYBOARD,i); + return 0; + } + + +char clk_battle_touch(int id,int xa,int ya,int xr,int yr) + { + int i; + side_touched=0; + i=clk_touch(id,xa,ya,xr,yr); + if (side_touched) clk_enter(id,xa,ya,xr,yr); + return i; + } + +#define CLK_PRESUN 12 +T_CLK_MAP clk_presun[]= + { + {H_SIPKY_S,561,378,598,407,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_SZ,530,387,560,418,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_Z,529,419,555,453,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_J,560,446,598,474,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_SV,599,387,628,418,clk_step,2,H_MS_DEFAULT}, + {H_SIPKY_V,605,420,632,454,clk_step,2,H_MS_DEFAULT}, + {MS_GAME_WIN,0,17,639,377,clk_battle_touch,2,-1}, + //{3,109,303,320,340,pick_item_,2,-1}, + //{2,320,303,531,340,pick_item_,2,-1}, + //{1,320,344,577,376,pick_item_,2,-1}, + //{0,63,344,320,376,pick_item_,2,-1}, + //{MS_GAME_WIN,0,17,639,377,clk_throw,2,-1}, + //{-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, + {1,147,0,205,14,clk_saveload,2,H_MS_DEFAULT}, + {0,207,0,265,14,clk_saveload,2,H_MS_DEFAULT}, + {-1,30,0,85,14,konec,2,H_MS_DEFAULT}, + {-1,565,408,593,447,clk_enter,2,H_MS_DEFAULT}, + {-1,0,0,640,480,empty_clk,0xff,-1}, + }; + +#define CLK_RUNES 3 +T_CLK_MAP clk_runes[]= + { + {-1,520,378,639,479,runes_mask,2+1,H_MS_DEFAULT}, + {-1,0,0,639,479,cancel_runes,0x8,H_MS_DEFAULT}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + + +#define CLK_POWER 5 +#define CLK_POWER_WHO 7 +T_CLK_MAP clk_power[]= + { + {0,535,391,637,411,power,2,H_MS_DEFAULT}, + {1,535,421,637,441,power,2,H_MS_DEFAULT}, + {2,535,431,637,471,power,2,H_MS_DEFAULT}, + {-1,0,0,639,377,cancel_power,2+8,-1}, + {-1,0,378,639,479,cancel_power,8,-1}, + {-1,54,378,497,479,ask_who_proc,2,-1}, + {-1,0,0,639,479,empty_clk,0xff,-1}, + }; + + +THUMAN *isplayer(int sector,THUMAN *h,char death) + { + short c=map_coord[sector].flags; + if (c & MC_PLAYER || (death && c & MC_DEAD_PLR)) + { + if (h==NULL) h=postavy;else h++; + while (h-postavyused && (h->lives || death) && h->sektor==sector) return h; + h++; + } + } + return NULL; + } + +int numplayers(int sector,char death) + { + int i,c; + THUMAN *h; + + for(i=0,c=0,h=postavy;iused && (death || h->lives) && h->sektor==sector) c++; + return c; + } + +TMOB *ismonster(int sector,TMOB *m) + { + if (mob_map[sector]) + { + if (m==NULL) m=mobs+mob_map[sector]-1;else + if (m->next) m=mobs+m->next-1;else return NULL; + } + else m=NULL; + return m; + } + +void presun_krok(EVENT_MSG *msg,void **user) + { + user; + if (msg->msg==E_INIT) return; + if (msg->msg==E_DONE) return; + postavy[select_player].actions--; + if (hromadny_utek) + { + int i; + destroy_player_map(); + for (i=0;imsg=-1; + } + +void poloz_vsechny_predmety() + { + int i; + + for(i=0;ivlastnosti[VLS_KOUZLA] & (SPL_STONED | SPL_FEAR)) return 0; + dsee++; +// if (battle) return 1; + prekvapeni=0; + if (d>p->dosah) return 0; + for(i=0;idir+2)&0x3)) break; + if (i==POCET_POSTAV) prekvapeni=!battle; + if (d==1) + { + ss=map_sectors[p->sector].step_next[p->dir]; + if (!(map_coord[ss].flags & MC_PLAYER)) return 0; + } + if (battle && p->vlajky & MOB_CASTING && get_spell_track(p->casting)) return 1; + if (d!=1) + { + if (prekvapeni) return 0; + } + return 1; + } + +void zacni_souboj(TMOB *p,int d,short sector) + { + int i; + //toto je jen test + battle=1; + attack_mob=p; + init_distance=d; + init_sector=sector; + map_coord[p->sector].flags |= MC_AUTOMAP; + for(i=0;imutok) mutok=0; + dmzhit=mutok; + zasah=utok-obrana; + } + else + { + int utok,obrana; + int ospod; + int x,y,z,zv; + + chaos=(chaos+1)/2; + ospod=obrance[VLS_OBRAN_L]/chaos; + x=rnd(utocnik[VLS_UTOK_H]-utocnik[VLS_UTOK_L]+1); + y=rnd(obrance[VLS_OBRAN_H]-ospod+1); + z=rnd(utocnik[VLS_MGSIL_H]-utocnik[VLS_MGSIL_L]+1); + dhit=utok=utocnik[VLS_UTOK_L]+x+(utocnik[VLS_SILA]*15+(utocnik[VLS_OBRAT])*10)/150+bonusplus; + obrana=ospod+y+(obrance[VLS_OBRAT]/5)+(flg & SPL_INVIS?10:0); + mutok=utocnik[VLS_MGSIL_L]+z; + zv=obrance[VLS_OHEN+utocnik[VLS_MGZIVEL]]; + zv=mgochrana(zv); + mutok=zv*mutok/100; + dmzhit=mutok; + zasah=utok-(ddef=obrana); + } + if (zasah<0) zasah=0; + if (zasah>0) zasah+=utocnik[VLS_DAMAGE],zasah=max(zasah,1); + ddostal=zasah; + zasah=zasah+mutok; + if (zasah>0) + { + zasah+=zbran; + if (zasah<1) zasah=1; + } + if (flg & SPL_SANC) zasah/=2; + if (flg & SPL_HSANC) zasah/=4; + if (flg & SPL_TVAR) zasah=-zasah; + return zasah; + } + +void rozhodni_o_poradi() + { + int celk=0; + int i,j; + short *r,mem; + + for(i=0;i378 && ms_last_event.x>510 && cur_mode!=MD_PRESUN; + if (cond) schovej_mysku(); + redraw_scene(); + if (!cancel_render && !norefresh) + { + if (cur_mode!=MD_PRESUN) + { + program_draw(); + draw_blood(0,0,0); + check_players_place(0); + } + showview(0,0,0,0); + if (neco_v_pohybu==2) neco_v_pohybu=0; else neco_v_pohybu=2; + calc_fly();mob_animuj(); + if (d_action!=NULL) do_delay_actions(); + } + if (cond) ukaz_mysku(); + if (neco_v_pohybu) + { + if (++counter>=maxwait && maxwait>0) neco_v_pohybu=0; + } + else + if (++countergroupnum && p->lives) + { + p->groupnum=t++; + for(j=i+1;q=&postavy[j],jsektor==q->sektor && p->direction==q->direction && q->used && q->lives) + q->groupnum=p->groupnum; + } + } +/* +int vyber_zacinajiciho(int att_player) + { + int gr; + THUMAN *p; + int i; + +// if (att_player==0xff) +// for(i=0;i=POCET_POSTAV?-POCET_POSTAV:1); + i++; + } + while ((!p->used || !p->actions)&& i<6); + return p-postavy; + } + +int vyber_prvniho(int att) + { + int grp; + int i; + + if (att==0xff) + for(i=0;iPOCET_POSTAV || att<0) + gr=cur_group,att=0xff; + else + gr=postavy[att].groupnum; + h=postavy; + for(i=0,h=postavy;iused || !h->lives || !h->actions || h->groupnum!=gr) ;i++,h++); + if (i==6) + if (att!=0xff) return att;else return group_sort[0]; + else + return i; + } + +void zacatek_kola() + { + int i; + THUMAN *p; + + SEND_LOG("(BATTLE) Start round",0,0); + build_player_map(); + cislo_kola++; + autostart_round=0; + for(i=0;iused) + { + postavy[i].programovano=0; + if (p->kondice && p->lives) + { + p->actions=get_ap(p->vlastnosti); + // if (p->actions) autostart_round=0; + } + else postavy[i].actions=0; + if (postavy[i].zvolene_akce!=NULL)free(postavy[i].zvolene_akce); + postavy[i].zvolene_akce=NewArr(HUM_ACTION,postavy[i].actions+1); + memset(postavy[i].zvolene_akce,0,(postavy[i].actions+1)*sizeof(HUM_ACTION)); + postavy[i].provadena_akce=postavy[i].zvolene_akce; + } + } + auto_group(); + sort_groups(); + select_player=vyber_hrace(att_player); + //att_player=vyber_prvniho(att_player); + //select_player=vyber_zacinajiciho(att_player); + zmen_skupinu(&postavy[select_player]); + viewsector=postavy[select_player].sektor; + viewdir=postavy[select_player].direction; + redraw_scene();cancel_render=1; + } + +char check_end_game() + { + THUMAN *p; + int i; + char end=1; + + for(i=0;iused && p->lives) + { + end=2; + if (p->groupnum==cur_group) return 0; + } + } + return end; + } + +void konec_kola() + { + int i;THUMAN *h;TMOB *m; + int j; + + SEND_LOG("(BATTLE) End round",0,0); + prekvapeni=0; + for(i=0,h=postavy;iused) + { + if (h->zvolene_akce!=NULL) free(h->zvolene_akce); + h->zvolene_akce=NULL; + h->programovano=0; + if (h->vlastnosti[VLS_KOUZLA] & SPL_REGEN && h->lives) + h->lives+=3; + player_check_death(h,1); + if (h->lives>h->vlastnosti[VLS_MAXHIT]) h->lives=h->vlastnosti[VLS_MAXHIT]; + } + for(i=0,m=mobs;ivlajky & MOB_LIVE && m->vlastnosti[VLS_KOUZLA] & SPL_REGEN) + { + m->lives+=3;if (m->lives>m->vlastnosti[VLS_MAXHIT]) m->lives=m->vlastnosti[VLS_MAXHIT]; + } + auto_group(); + sort_groups(); + select_player=-1; + GlobEvent(MAGLOB_ONROUND,viewsector,viewdir); + sleep_ticks+=MAX_SLEEP/12; + if (sleep_ticks>MAX_SLEEP) sleep_ticks=MAX_SLEEP; + for(i=0,j=0;imsg==E_KEYBOARD && !pass_zavora) + { + msg->msg=-2; + delete_from_timer(TM_SCENE); + delete_from_timer(TM_FLY); + wire_save_load(2); + bott_draw(1); + cancel_render=1; + } + } + +static char clk_goon(int id,int xa,int ya,int xr,int yr) + { + id,xa,ya,xr,yr; + send_message(E_KEYBOARD,13); + return 1; + } + +#define CLK_END_GAME 2 +T_CLK_MAP clk_end_game[]= + { + {-1,0,0,639,479,clk_goon,8+2,H_MS_DEFAULT}, + {-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT}, + }; + + +EVENT_PROC(end_game_end_phase) + { + static wait=0; + WHEN_MSG(E_TIMER) + { + if (pass_zavora) return; + if (wait==2) + { + send_message(E_ADD,E_KEYBOARD,kbd_end_game); + send_message(E_DONE,E_TIMER,end_game_end_phase); + change_click_map(clk_end_game,CLK_END_GAME); + } + else wait++; + } + WHEN_MSG(E_INIT) + wait=0; + user_ptr; + } + +void wire_end_game() + { + int i; + if (cur_mode==MD_END_GAME) return; + konec_kola(); + battle=0;running_battle=0; + unwire_proc(); + for(i=0;imsg==E_KEYBOARD && ((*(int *)msg->data)>>8)==28 && !pass_zavora) + { + unwire_proc(); + wire_jadro_souboje(); + msg->msg=-1; + } + } + +void wire_presun_postavy(); +void unwire_presun_postavy() + { + disable_click_map(); + send_message(E_DONE,E_KEYBOARD,game_keyboard); + send_message(E_DONE,E_KROK,presun_krok); + send_message(E_DONE,E_KEYBOARD,konec_presunu); + delete_from_timer(TM_SCENE); + cur_mode=MD_INBATTLE; + sort_groups(); + wire_proc=wire_presun_postavy; + hromadny_utek=0; + } + +void wire_presun_postavy() + { + unwire_proc(); + + moving_player=select_player; + change_click_map(clk_presun,CLK_PRESUN); + send_message(E_ADD,E_KEYBOARD,game_keyboard); + send_message(E_ADD,E_KROK,presun_krok); + send_message(E_ADD,E_KEYBOARD,konec_presunu); + cur_mode=MD_PRESUN; + auto_group(); + sort_groups(); + bott_draw(1); + redraw_scene(); + add_to_timer(TM_SCENE,gamespeed,-1,hrat_souboj); + showview(0,0,0,0); + unwire_proc=unwire_presun_postavy; + cancel_render=1; + } + +static DWORD SPozdrzeno=0; + +static char JePozdrzeno() +{ + return GetTickCount()sektor; + viewdir=p->direction; + pozdrz_akci(); + hold_timer(TM_SCENE,1); + redraw_scene(); + cancel_render=1; + program_draw(); + showview(0,0,0,0); + hold_timer(TM_SCENE,0); + + } + +int hromadny_utek; +static int UtekHromadne(int sector) + { + int minact=999; + int i; + int p=0; + for (i=0;i2) + { + int wf=weigth_defect(postavy+i)+2; + if (postavy[i].provadena_akce==NULL || postavy[i].provadena_akce->action!=AC_RUN) return 0; + if (postavy[i].utek1?minact:0; + } + +void utek_postavy(THUMAN *p) + { + int minact=0; + p->actions=p->utek; + if (game_extras & EX_GROUP_FLEE && (minact=UtekHromadne(p->sektor))!=0) + { + int i; + p->actions=minact; + hromadny_utek=p->sektor; + for (i=0;isektor) + { + int wf=weigth_defect(postavy+i)+2; + postavy[i].kondice-=minact*wf; + if (postavy[i].kondice<0) postavy[i].kondice=0; + if (postavy+i!=p) postavy[i].programovano=0; + } + } + else + { + int wf=weigth_defect(p)+2; + hromadny_utek=0; + if (p->actions) + { + p->kondice-=p->actions*wf; + if (p->kondice<0) + { + p->actions+=p->kondice/wf; + p->kondice=0; + } + } + } + wire_presun_postavy(); + prejdi_na_pohled(p); + } + +int trace_path(sector,dir) + { + int mm,p,c=5; + int r=rnd(2); + do + { + if ((mm=mob_map[sector])!=0) + { + if (mobs[mm-1].stay_strategy & MOB_BIG) return 0; + if (mobs[mm-1].next!=0 && r==1) mm=mobs[mm-1].next; + switch (dir) + { + case 0: p=mobs[mm-1].locx-128;break; + case 1: p=mobs[mm-1].locy-128;break; + case 2: p=-(mobs[mm-1].locx-128);break; + case 3: p=-(mobs[mm-1].locy-128);break; + } + if (p<-12) return -24; + else if (p>12) return +24; + else return 0; + }/* return rnd(3)-1;*/ + if (map_sides[(sector<<2)+dir].flags & SD_THING_IMPS) return -255; + sector=map_sectors[sector].step_next[dir]; + c--; + } + while (c); + return -255; + } + +void hod_dykou(THUMAN *p,int where,int bonus) + { + short *pp; + int i; + int ps; + LETICI_VEC *v; + + ps=trace_path(p->sektor,p->direction); + if (ps==-255) return; + pp=picked_item; + picked_item=getmem(2*sizeof(short)); + picked_item[0]=p->wearing[where]; + picked_item[1]=0; + v=throw_fly(320,100,0); + v->ypos=ps; + v->hit_bonus=(p->vlastnosti[VLS_OBRAT]*3+p->vlastnosti[VLS_SILA]*2)/30+bonus; + v->damage=0; + for(i=0;iinv_size;i++) + { + int it; + + it=p->inv[i]; + if (it--) + { + if (glob_items[it].druh==TYP_VRHACI && glob_items[it].umisteni==PL_RUKA) + { + p->wearing[where]=it+1; + p->inv[i]=0; + break; + } + } + } + if(i==p->inv_size) p->wearing[where]=0; + picked_item=pp; + } + +void vystrel_sip(THUMAN *p,int bonus) + { + short *pp; + int ps; + int i; + int x; + LETICI_VEC *v; + TITEM *t; + + ps=trace_path(p->sektor,p->direction); + if (ps==-255) return; + if (!p->sipy) + { + char s[100]; + + sprintf(s,texty[72],p->jmeno); + bott_disp_text(s); + return; + } + for(i=0;isipy--; + v=throw_fly(320,100,1); + v->ypos=ps; + x=rnd(p->vlastnosti[VLS_UTOK_H]-p->vlastnosti[VLS_UTOK_L]); + v->hit_bonus=x+p->vlastnosti[VLS_UTOK_L]+(p->vlastnosti[VLS_SILA]*10+p->vlastnosti[VLS_OBRAT]*15)/150+bonus; + v->damage=p->vlastnosti[VLS_DAMAGE]; + picked_item=pp; + t->zmeny[VLS_MGSIL_H]=p->vlastnosti[VLS_MGSIL_H]; //adjust zmen v magickem utoku + t->zmeny[VLS_MGSIL_L]=p->vlastnosti[VLS_MGSIL_L]; + t->zmeny[VLS_MGZIVEL]=p->vlastnosti[VLS_MGZIVEL]; + play_sample_at_sector(H_SND_SIP1+rnd(2),0,0,0,0); + neco_v_pohybu=1; + } + +char is_useable_weapon(int i) + { + if (!i) return 0; + i--; + switch (glob_items[i].druh) + { + case TYP_UTOC: + case TYP_VRHACI: + case TYP_STRELNA: + case TYP_SVITEK:return 1; + default: return 0; + } + } + +int select_weapon(THUMAN *p,char ask) + { + char lp,rp; + int li,ri; + char *c; + + li=p->wearing[PO_RUKA_L]; + ri=p->wearing[PO_RUKA_R]; + lp=is_useable_weapon(li); + rp=is_useable_weapon(ri); + if (!lp && !rp) return 2; + if (lp && !rp) return 0; + if (!lp && rp) return 1; + li--; + ri--; + if (glob_items[li].druh==glob_items[ri].druh && glob_items[li].druh==TYP_UTOC) return 2; + if (!ask) return rnd(2); + unwire_proc(); + c=alloca(strlen(p->jmeno)+strlen(texty[82])+1); + sprintf(c,texty[82],p->jmeno); + lp=message(2,0,1,"",c,texty[83],texty[84]); + wire_proc(); + return lp; + } + +static int vypocti_bonus(THUMAN *p,int vybrana_zbran) + { + int bonus; + if (vybrana_zbran>-1) + if (vybrana_zbran>0) bonus=p->bonus_zbrani[glob_items[vybrana_zbran-1].typ_zbrane]; + else bonus=p->bonus_zbrani[TPW_OST]; + else bonus=0; + return bonus; + } + +static void pouzij_svitek(THUMAN *p,int ruka) + { + int it=p->wearing[ruka]-1; + short s[2]; + + thing_cast(glob_items[it].spell,p-postavy,p->sektor,NULL,0); + if (glob_items[it].magie==1) + { + s[0]=it+1; + s[1]=0; + destroy_items(s); + p->wearing[ruka]=0; + } + else + { + it=(p->wearing[ruka]=duplic_item(it+1)); + it--; + glob_items[it].magie--; + } + } + +static void play_weapon_anim(int anim_num,int hitpos) + { + char count_save=global_anim_counter; + int battlespeed=gamespeed-gamespeed*gamespeedbattle/5; + + if (anim_num==0) return; + hold_timer(TM_SCENE,1); + if (battlespeed<1) battlespeed=1; + add_to_timer(TM_SCENE2,battlespeed,-1,hrat_souboj); + play_big_mgif_animation(anim_num+face_arr[4]); + do + { + while (global_anim_counter==count_save) + { + do_events(); + } + count_save=global_anim_counter; + } + while (hitpos-- && running_anm); + delete_from_timer(TM_SCENE2); + hold_timer(TM_SCENE,0); + cancel_render=1; + } + +void pouzij_zbran(THUMAN *p,int ruka) + { + int itm,where; + TITEM *it; + int bonus; + int wf=weigth_defect(p)+1; + + + p->kondice-=wf; + if (ruka==2) ruka=plr_switcher[p-postavy]; + where=PO_RUKA_L+ruka; + itm=p->wearing[where]; + SEND_LOG("(BATTLE) Player uses weapon %d.in %s hand",itm,where?"right":"left"); + if (p->stare_vls[VLS_KOUZLA] & SPL_INVIS) + { + p->stare_vls[VLS_KOUZLA]&=~SPL_INVIS; + prepocitat_postavu(p); + build_all_players(); + } + vybrana_zbran=itm; + bonus=vypocti_bonus(p,itm); + if (itm>0) + memcpy(&p->vlastnosti[VLS_MGSIL_L],&glob_items[itm-1].zmeny[VLS_MGSIL_L],3*sizeof(short)); + else + memset(&p->vlastnosti[VLS_MGSIL_L],0,3*sizeof(short)); + if (!itm || (it=&glob_items[itm-1])->druh==TYP_UTOC) + { + TMOB *m;int mm,chaos; + mm=vyber_potvoru(p->sektor,p->direction,&chaos); + if (mm>=0) + { + TITEM *it=glob_items+itm-1; + m=mobs+mm; + bott_draw(1); + anim_mirror=ruka==0; + prejdi_na_pohled(p); + if (itm) play_weapon_anim(it->weapon_attack,it->hitpos); + if (utok_na_sektor(p,m,chaos,bonus)>0 && itm && rnd(100)+1magie) + thing_cast(it->spell,p-postavy,p->sektor,m,1); + } + } + else + { + prejdi_na_pohled(p); + switch(it->druh) + { + case TYP_VRHACI:hod_dykou(p,where,bonus);break; + case TYP_STRELNA:vystrel_sip(p,bonus);break; + case TYP_SVITEK:pouzij_svitek(p,where);break; + } + } + bott_draw(0); + } + +static word last_sector; +static char valid_sectors(word sector) + { + int pp; + int i; + + last_sector=sector; + if (mob_map[sector]) return 0; //nevyhovujici + pp=map_sectors[sector].sector_type; + if (pp==S_DIRA || ISTELEPORT(pp)) return 0; + for (i=0;i<4;i++) if (map_sectors[sector].step_next[i] && mob_map[map_sectors[sector].step_next[i]]) return 0; + return 1; + } + + +static char StrachPostavy(THUMAN *p) +{ + word *cesta; + int i; + int ln; + int wf=weigth_defect(p)+1; + + prejdi_na_pohled(p); + cur_group=p->groupnum; + for(select_player=0;select_player<6;select_player++) if (postavy+select_player==p) break; + bott_draw(0); + labyrinth_find_path(p->sektor,65535,SD_PLAY_IMPS,valid_sectors,NULL); + ln=labyrinth_find_path(p->sektor,last_sector,SD_PLAY_IMPS,valid_sectors,&cesta); + if (cesta[0]==0) {free(cesta);return 0;} + for (i=0;i<6 && cesta[i] && p->kondice ;i++) + { + int dir; + for (dir=0;dir<4;dir++) if (map_sectors[p->sektor].step_next[dir]==cesta[i]) break; + destroy_player_map(); + p->direction=dir; + p->sektor=cesta[i]; + build_player_map(); + prejdi_na_pohled(p); + Sleep(200); + p->kondice-=wf; + } + p->provadena_akce+=p->programovano-1; + p->programovano=1; + free(cesta); + return 1; +} + +void jadro_souboje(EVENT_MSG *msg,void **unused) //!!!! Jadro souboje + { + static char nowait=0; + unused; + + if (msg->msg==E_IDLE && (!neco_v_pohybu || !battle || nowait)&& !norefresh && !cancel_render) + { + short nxt; + + if (check_end_game()==1) + { + wire_end_game(); + return; + } + vybrana_zbran=-1; + cancel_render=1; + nxt=*prave_hraje++; + anim_mirror=0; + if (nxt) + { + if (nxt>0) + { + nxt--; + SEND_LOG("(BATTLE) Mobile action (%d. %s)",nxt,mobs[nxt].name); + nowait=akce_moba_zac(&mobs[nxt]) && *prave_hraje>0; + neco_v_pohybu=1; + cislo_potvory=nxt; + } + else + if(nxt==-255) + { + int i; + SEND_LOG("(BATTLE) Ending round...",nxt,mobs[nxt].name); + delete_from_timer(TM_SCENE); + add_to_timer(TM_SCENE,gamespeed,-1,refresh_scene); + for(i=0;iprogramovano && p->lives) + { + plr_switcher[select_player]=!plr_switcher[select_player]; + cur_group=p->groupnum; + cancel_render=1; + if (p->kondice || p->provadena_akce->action==AC_STAND) + { + if (p->vlastnosti[VLS_KOUZLA] & SPL_FEAR && StrachPostavy(p)) + {} + else + { + SEND_LOG("(BATTLE) Player Action '%s', number: %d",p->jmeno,p->provadena_akce->action); + switch(p->provadena_akce->action) + { + case AC_MOVE: + { + int wf=weigth_defect(p)+1; + p->actions++; + p->kondice-=p->actions*wf; + if (p->kondice<0) + { + p->actions+=p->kondice*wf; + p->kondice=0; + if (p->actions<0) + { + p->actions=0; + break; + } + } + viewsector=p->sektor; + viewdir=p->direction; + wire_presun_postavy(); + break; + } + case AC_ATTACK:pouzij_zbran(p,p->provadena_akce->data1);break; + case AC_ARMOR:souboje_prezbrojeni(nxt); + bott_draw(1); + other_draw(); + break; + case AC_THROW: + { + int x,y; + memcpy(&picked_item,&p->provadena_akce->data2,sizeof(short *)); + x=p->provadena_akce->data1; + y=(x>>8)*2;x=(x & 0xff)*4; + prejdi_na_pohled(p); + throw_fly(x,y,0); + cislo_potvory=-2; + neco_v_pohybu=1; + } + case AC_STAND:pomala_regenerace_postavy(p);break; + case AC_RUN:utek_postavy(p);break; + case AC_MAGIC: + prejdi_na_pohled(p); + bott_draw(1); + teleport_target=p->provadena_akce->data2; + cast(p->provadena_akce->data1,p,select_player,0); + cislo_potvory=-2; + break; + } + } + } + neco_v_pohybu=1; + p->provadena_akce++; + p->programovano--; + } + } + } + else + { + nowait=0; + konec_kola(); + check_all_mobs_battle(); + mouse_set_default(H_MS_DEFAULT); + if (battle) + { + delete_from_timer(TM_SCENE); + zacatek_kola(); + unwire_proc(); + wire_programming(); + } + else + { + int i; + THUMAN *p; + + SEND_LOG("(BATTLE) Leaving battle",0,0); + prekvapeni=0; + unwire_proc(); + wire_main_functs(); + bott_draw(1); + running_battle=0; + for(i=0;p=&postavy[i],isektor!=viewsector || !p->used || !p->groupnum);i++); + if (i==POCET_POSTAV) + for(i=0;p=&postavy[i],iused || !p->groupnum);i++); + cur_group=postavy[i].groupnum; + viewsector=postavy[i].sektor; + viewdir=postavy[i].direction; + build_player_map(); + GlobEvent(MAGLOB_AFTERBATTLE,viewsector,viewdir); + } + msg->msg=-2; + } + } + } + +void wire_jadro_souboje() + { + int battlespeed=gamespeed-gamespeed*gamespeedbattle/5; + recalc_volumes(viewsector,viewdir); + if (battlespeed<1) battlespeed=1; + add_to_timer(TM_SCENE,battlespeed,-1,hrat_souboj); + send_message(E_ADD,E_IDLE,jadro_souboje); + mouse_set_default(H_MS_SOUBOJ); + unwire_proc=unwire_jadro_souboje; + cur_mode=MD_INBATTLE; + pgm_help=10; + } + +void unwire_jadro_souboje() + { + delete_from_timer(TM_SCENE); + send_message(E_DONE,E_IDLE,jadro_souboje); + mouse_set_default(H_MS_DEFAULT); + wire_proc=wire_jadro_souboje; + pgm_help=0; + } + +void fill_rune(char *d,int i) + { + int x,y;char *dd; + + dd=((char *)d)+6+512; + for(y=378;y<480;y++) + { + word *z; + z=GetScreenAdr()+y*scr_linelen2; + for(x=520;x<640;x++) + if (*dd++==i) z[x]=z[x]-((z[x] & RGB555(28,28,28))>>2); + } + + } + +static void *runebar; +static char *rune_name=NULL; + +void display_rune_bar() + { + short coords[][2]={{3,26},{32,26},{61,26},{90,26},{18,64},{47,64},{76,64}}; + char c; + int i; + + schovej_mysku(); + if (runebar!=NULL) put_picture(520,378,runebar); + else + { + put_picture(520,378,ablock(H_RUNEBAR1+sel_zivel)); + c=runes[sel_zivel]; + for(i=0;i<7;i++,c>>=1) + if (!(c & 1)) put_picture(520+coords[i][0],378+coords[i][1],ablock(H_RUNEHOLE)); + else if (!get_rune_enable(&postavy[select_player],(sel_zivel*7+i)*3)) fill_rune((char *)ablock(H_RUNEMASK),i+6); + if (sel_zivel) trans_bar(520,378,sel_zivel*24,22,0); + if (sel_zivel!=4)trans_bar(544+sel_zivel*24,378,96-sel_zivel*24,22,0); + runebar=getmem(120*102*2+6); + get_picture(520,378,120,102,runebar); + } + ukaz_mysku(); + if (je_myska_zobrazena())showview(520,378,120,102); + } + + + +void rune_bar_redrawing() + { + redraw_scene(); + if (!norefresh && !cancel_render) + { + schovej_mysku(); + program_draw(); + display_rune_bar(); + ukaz_mysku(); + showview(0,0,0,0); + } + } + + +void display_power_bar(char drw) + { + int coords[][2]={{20,11},{20,41},{20,71}}; + int i; + + schovej_mysku(); + put_picture(520,378,ablock(H_POWERBAR)); + for(i=0;i<3;i++) + put_8bit_clipped(ablock(H_POWERLED),520+coords[i][0]+(378+coords[i][1])*scr_linelen2+GetScreenAdr(),24*powers[i],21,24); + ukaz_mysku(); + if (drw) showview(520,378,120,102); + } + +void display_power_bar_tm(THE_TIMER *tm) + { + tm; + display_power_bar(1); + } + +void wire_select_rune(); +void unwire_select_rune(); +void wire_select_power(); + +char cancel_power(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr;id; + schovej_mysku(); + unwire_proc(); + magic_data->action=0; + after_spell_wire(); + mouse_set_default(H_MS_DEFAULT); + ukaz_mysku(); + return 1; + } + +char ask_who_proc(int id,int xa,int ya,int xr,int yr) + { + THUMAN *p; + int i; + word *xs; + + xs=ablock(H_OKNO); + i=xr/xs[0];yr;xa;ya;id; + if (isektor!=viewsector; + if (p->used) + if ((!far_play && !c || !death_play && c) && death_play==(p->lives==0)) + { + if (get_spell_teleport(magic_data->data1)) + if ((magic_data->data2=select_teleport_target())==0) + { + cancel_power(id,xa,ya,xr,yr); + return 1; + } + magic_data->data1+=(i+1)<<9; + magic_data->action=AC_MAGIC; + if (battle) souboje_vybrano(AC_MAGIC); + unwire_proc(); + after_spell_wire(); + mouse_set_default(H_MS_DEFAULT); + return 1; + } + } + return 0; + } + +void vyber_cil(int typ) + { + death_play=(typ==3)?1:0; + far_play=(typ==4)?1:0; + change_click_map(clk_power,CLK_POWER_WHO); + mouse_set_default(H_MS_WHO); + } + +char power(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr; + if (powers[id]==1) return 1; + schovej_mysku(); + display_power_bar(0); + trans_bar(520+44,378+11+30*id,76,24,RGB555(31,31,31)); + mouse_set_default(H_MS_DEFAULT); + ukaz_mysku(); + showview(520,378,120,102); + magic_data->data1-=magic_data->data1 % 3; + magic_data->data1+=id; + id=magic_data->data1; + if ((id=ask_who(id))>1) + { + vyber_cil(id); + return 1; + } + magic_data->action=AC_MAGIC; + if (get_spell_teleport(magic_data->data1)) + if ((magic_data->data2=select_teleport_target())==0) + { + cancel_power(id,xa,ya,xr,yr); + return 1; + } + if (id==1) magic_data->data1+=(select_player+1)<<9; + schovej_mysku(); + if (battle) souboje_vybrano(AC_MAGIC); + unwire_proc(); + after_spell_wire(); + ukaz_mysku(); + return 1; + } + +char runes_mask(int id,int xa,int ya,int xr,int yr) + { + char *c; + int cc; + short *d; + + id;ya;xa; + d=ablock(H_RUNEMASK); + c=((char *)d)+6+512+xr+yr*d[0]; + cc=*c-6; + if (*c) + if (*c<6 && ms_last_event.event_type & 0x2) sel_zivel=*c-1; + else if (runes[sel_zivel] & (1<data1=x; + unwire_select_rune(); + wire_select_power(); + schovej_mysku(); + fill_rune((char *)d,*c); + ukaz_mysku(); + showview(520,378,120,102); + return 1; + } + else + { + rune_name=get_rune_name(x); + } + } + if (cc<0) rune_name=NULL; + free(runebar);runebar=NULL; + display_rune_bar(); + return 1; + } + +char cancel_runes(int id,int xa,int ya,int xr,int yr) + { + xa;ya;xr;yr;id; + rune_name=NULL; + schovej_mysku(); + unwire_select_rune(); + magic_data->action=0; + after_spell_wire(); + ukaz_mysku(); + return 1; + } + +void unwire_select_rune() + { + wire_proc=wire_select_rune; + delete_from_timer(TM_DELAIER); + delete_from_timer(TM_SCENE); + cancel_render=1; + free(runebar);runebar=NULL; + } + +void wire_select_rune() + { + THUMAN *p; + HUM_ACTION *c; + + mute_all_tracks(0); + p=&postavy[select_player]; + c=p->zvolene_akce;while (c->action) c++; + magic_data=c; + c++; + c->action=0; + unwire_proc(); + change_click_map(clk_runes,CLK_RUNES); + add_to_timer(TM_DELAIER,12,1,display_rune_bar); + add_to_timer(TM_SCENE,gamespeed,-1,rune_bar_redrawing); + unwire_proc=unwire_select_rune; + cancel_render=1; + } + +void wire_select_rune_fly() + { + mute_all_tracks(0); + unwire_proc(); + change_click_map(clk_runes,CLK_RUNES); + add_to_timer(TM_DELAIER,12,1,display_rune_bar); + add_to_timer(TM_SCENE,gamespeed,-1,rune_bar_redrawing); + unwire_proc=unwire_select_rune; + cancel_render=1; + } + +void unwire_select_power() + { + rune_name=NULL; + delete_from_timer(TM_DELAIER); + } + +void wire_select_power() + { + THUMAN *p; + int i; + + p=&postavy[select_player]; + mute_all_tracks(0); + unwire_proc(); + for(i=0;i<3;i++) powers[i]=get_spell_color(p,magic_data->data1+i); + change_click_map(clk_power,CLK_POWER); + unwire_proc=unwire_select_power; + add_to_timer(TM_DELAIER,12,1,display_power_bar_tm); + } + + + +void program_draw() + { + int x=54+74/2; + int i,j,maxy=0; + + maxy; + schovej_mysku(); + for(j=0;jmaxy) maxy=y; + } + if (!maxy && (pgm_help || rune_name!=NULL)) maxy+=10; + if (maxy) + { + maxy+=5; + trans_bar(0,377-maxy,640,maxy,0); + } + for(j=0;jaction+40]); + outtext(texty[c->action+40]); + c++; + y+=+10; + } + x+=74; + } + if(pgm_help || rune_name!=NULL) + { + char *c; + + if (rune_name!=NULL) c=rune_name;else c=texty[40+pgm_help]; + set_font(H_FLITT5,PRG_HELP_COLOR); + set_aligned_position(580,376,1,2,c); + outtext(c); + } + ukaz_mysku(); + } + + +void souboje_redrawing() + { + if (neco_v_pohybu) calc_mobs(); + calc_animations(); + redraw_scene(); + if (!norefresh && !cancel_render) + { + schovej_mysku(); + program_draw(); + ukaz_mysku(); + showview(0,0,0,0); + } + } + + +void souboje_stisknout(int d) + { + update_mysky(); + schovej_mysku(); + d--; + d*=105; + put_8bit_clipped(ablock(H_BATTLE_CLICK),378*scr_linelen2+520+GetScreenAdr(),d,120,102); + ukaz_mysku(); + showview(520,378,120,102); + cancel_render=1; + } + +static void souboje_dalsi() + { + int i,j=12,cd; + for(i=0;group_sort[i]!=select_player;i++); + cd=postavy[select_player].groupnum; + do + { + i++; + if (i>=POCET_POSTAV) i=0; + select_player=group_sort[i]; + j--; + } + while ((!postavy[select_player].used || !postavy[select_player].actions || (postavy[select_player].groupnum!=cd && j>6)) && j); + viewsector=postavy[select_player].sektor; + viewdir=postavy[select_player].direction; + } + +void souboje_vybrano(int d) + { + if (d==AC_STAND || d==AC_RUN) postavy[select_player].actions=0; + else postavy[select_player].actions--; + postavy[select_player].programovano++; + if (!postavy[select_player].actions) + souboje_dalsi(); + bott_draw(1); + } + +void zrusit_akce() + { + HUM_ACTION *c; + + c=postavy[select_player].zvolene_akce; + while (c->action) + if (c->action==AC_THROW) + { + poloz_vsechny_predmety(); + memcpy(&picked_item,&c->data2,sizeof(short *)); + c++; + } + else c++; + postavy[select_player].zvolene_akce->action=0; + postavy[select_player].actions=get_ap(postavy[select_player].vlastnosti);; + postavy[select_player].programovano=0; + postavy[select_player].utek=0; + pick_set_cursor(); + bott_draw(1); + } + +char souboje_clk_throw(int id,int xa,int ya,int xr,int yr) + { + HUM_ACTION *c; + + if (postavy[select_player].actions==0) return 0; + if (picked_item==NULL) return 0; + postavy[select_player].direction=viewdir; + c=postavy[select_player].zvolene_akce;while (c->action) c++; + c->action=AC_THROW; + memcpy(&c->data2,&picked_item,sizeof(short *));picked_item=NULL; + c->data1=xa/4+(ya/2)*256; + c++; + c->action=0; + pick_set_cursor();id;xr;yr; + souboje_vybrano(AC_THROW); + return 1; + } + + +char mask_click_help(int id,int xa,int ya,int xr,int yr) + { + char *c; + int d; + word *mask; + + id;xa;ya; + mask=(word *)ablock(H_BATTLE_MASK); + c=(char *)mask+6+512; + c+=yr*mask[0]+xr; + d=*c; + if (d) pgm_help=d; + return 1; + } + +char mask_click_help_clear(int id,int xa,int ya,int xr,int yr) + { + id;xa;ya; + xr;yr; + pgm_help=0; + return 1; + } + +static void zahajit_kolo(char prekvapeni) + { + int i,j; + + for(i=0;isektor,dir=p->direction; + char monster=0; + char monster_far=0; + char lnear=1; + int counter=5; + short w1,w2,dw1,dw2,w; + + while (~map_sides[(sect<<2)+dir].flags & SD_PLAY_IMPS) + { + int m1,m2; + sect=map_sectors[sect].step_next[dir]; + if (numplayers(sect,0)>2) break; + m1=mob_map[sect]-1;if (m1>=0) m2=mobs[m1].next-1;else m2=-1; + if ((m1>=0 && mobs[m1].vlajky & MOB_IN_BATTLE) || (m2>=0 && mobs[m2].vlajky & MOB_IN_BATTLE)) + if (lnear) monster=1;else monster_far=1; + lnear=0;counter--;if(!counter) break; + } + w1=p->wearing[PO_RUKA_L];w2=p->wearing[PO_RUKA_R]; + if (w1) dw1=glob_items[w1-1].druh;else dw1=-1; + if (w2) dw2=glob_items[w2-1].druh;else dw2=-1; + w=0; + if (dw1==TYP_STRELNA && p->sipy || dw1==TYP_VRHACI) w|=1; + if (dw2==TYP_STRELNA && p->sipy || dw2==TYP_VRHACI) w|=2; + if (w==0) w=select_weapon(p,0); + else if (w==3) w=select_weapon(p,0),monster|=monster_far; + else w--,monster|=monster_far; + if (p->used && !p->programovano && p->lives) + if (prekvapeni || !p->actions || !autoattack || !monster) + { + p->programovano++;p->zvolene_akce->action=AC_STAND; + } + else + { + for(j=0;jactions;j++) + { + p->zvolene_akce[j].action=AC_ATTACK; + p->zvolene_akce[j].data1=w; + } + p->programovano=(char)p->actions; + } + } + rozhodni_o_poradi(); + unwire_proc(); + wire_jadro_souboje(); + send_message(E_KOUZLO_KOLO); + } + +char mask_click(int id,int xa,int ya,int xr,int yr) + { + char *c; + int d; + word *mask; + + id;xa;ya; + mask=(word *)ablock(H_BATTLE_MASK); + c=(char *)mask+6+512; + c+=yr*mask[0]+xr; + d=*c; + if (d) + { + souboje_stisknout(d); + switch(d) + { + case AC_RUN: postavy[select_player].utek=5+postavy[select_player].actions; + case AC_ATTACK: + case AC_STAND: + case AC_ARMOR: + case AC_MOVE: + case AC_MAGIC:if (postavy[select_player].actions) + { + HUM_ACTION *c; + postavy[select_player].direction=viewdir; + c=postavy[select_player].zvolene_akce;while (c->action) c++; + if (d==AC_MAGIC) + { + wire_select_rune(); + return 1; + } + c->action=d; + if (d==AC_ATTACK) c->data1=select_weapon(&postavy[select_player],1); + c++; + c->action=0; + souboje_vybrano(d); + } + break; + case AC_CANCEL:zrusit_akce();break; + case AC_START:zahajit_kolo(0); + souboje_stisknout(d); + return 0; + break; + } + return 0; + } + bott_draw(1); + return 1; + } +void fix_group_direction() + { + int i,g; + + g=postavy[select_player].groupnum; + for(i=0;imsg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + while (_bios_keybrd(_KEYBRD_READY) ) _bios_keybrd(_KEYBRD_READ); + switch (c) + { + case 1:konec(0,0,0,0,0);break; + case 'M':souboje_turn(1);break; + case 'K':souboje_turn(-1);break; + case '=':unwire_proc();cancel_render=1;wire_save_load(0);break; + case '>':game_setup(0,0,0,0,0);break; + case 57:souboje_dalsi();bott_draw(1);break; + case 15: + case 50: + if (GlobEvent(MAGLOB_BEFOREMAPOPEN,viewsector,viewdir)) + show_automap(1); + break; + case 0x17:unwire_proc(); + wire_inv_mode(human_selected); + case 82:group_all();break; + CASE_KEY_1_6:c=group_sort[c-2]; + if (postavy[c].used) + { + select_player=c; + zmen_skupinu(postavy+c); + bott_draw(1); + } + break; + } + } + + } + +void unwire_programming() + { + disable_click_map(); + send_message(E_DONE,E_KEYBOARD,programming_keyboard); + delete_from_timer(TM_SCENE); + cancel_render=1; + wire_proc=wire_programming; + } + + + +void wire_programming() + { + schovej_mysku(); + after_spell_wire=wire_programming; + cur_mode=MD_INBATTLE; + battle_mode=0; + change_click_map(clk_souboje,CLK_SOUBOJE); + send_message(E_ADD,E_KEYBOARD,programming_keyboard); + add_to_timer(TM_SCENE,gamespeed,-1,souboje_redrawing); + ukaz_mysku(); + unwire_proc=unwire_programming; + bott_draw(1); + showview(0,0,0,0); + recalc_volumes(viewsector,viewdir); + if (autostart_round) zahajit_kolo(1); + } + +void wait_to_stop(EVENT_MSG *msg,void **unused) + { + + unused; + if (msg->msg==E_IDLE) + if (!neco_v_pohybu) + { + unwire_proc(); + calc_mobs(); + mouse_set_default(H_MS_DEFAULT); + refresh_scene(); + cancel_render=1; + if (prekvapeni) zahajit_kolo(1);else wire_programming(); + msg->msg=-2; + } + } + + +void start_battle() + { + spell_cast=0; + if (check_end_game()) + { + wire_end_game(); + return; + } + if (!GlobEvent(MAGLOB_BEFOREBATTLE,viewsector,viewdir)) + { + int i; + battle=0; + for (i=0;iname:"(NULL)",0); + poloz_vsechny_predmety(); + zacatek_kola(); + running_battle=1; +// select_player=att_player; + cislo_kola=0; + if (prekvapeni) + { + unwire_proc(); + mouse_set_default(H_MS_SOUBOJ); + zahajit_kolo(1); + } + else + { + unwire_proc(); + wire_programming(); + } + } + } + +int pocet_zivych(int sector) + { + char z=0; + int i; + for(i=0;iused && p->lives && p->sektor==sector) z++; + } + return z; + } + +void manashield_check(short *vls,short *lives,short *mana,int dostal) + { + if (vls[VLS_KOUZLA] & SPL_MANASHIELD) + { + *mana-=*mana>dostal?dostal:*mana; + if (!*mana) vls[VLS_KOUZLA]&=~SPL_MANASHIELD; + } + else + *lives-=dostal; + } + + + +char zasah_veci(int sector,TFLY *fl) + { + int mob1,mob2; + TMOB *m1,*m2; + TITEM *it; + + m1=NULL; + m2=NULL; + if (fl->items==NULL && fl->item==0) return 0; + if (fl->items==NULL) it=glob_items+fl->item-1;else it=&glob_items[*(fl->items)-1]; + if (fl->flags & FLY_DESTROY_SEQ || !fl->speed) return 0; + if (fl->flags & FLY_DESTROY) + { + if (mob_map[sector] && fl->owner>=0) + { + if (fl->owner>=0) select_player=fl->owner-1; + if (it->druh!=TYP_VRHACI) return 1; + if (it->magie) area_cast(it->spell,sector,fl->owner,1); + mob1=mob_map[sector]-MOB_START;m1=&mobs[mob1]; + mob2=m1->next-MOB_START; + if (mob2>=0) + { + m2=&mobs[mob2]; + if (m2->vlajky & MOB_PASSABLE) m2=NULL;//pruchozi nestvury nemaji affekt na hozenou vec + } + else m2=NULL; + if (m1->vlajky & MOB_PASSABLE) if (m2!=NULL) m1=m2;else return 0; + if (m2==NULL) + { + mob_hit(m1,vypocet_zasahu(it->zmeny,m1->vlastnosti,1,fl->damage,fl->hit_bonus)); + m1->dir=fl->smer+2&3; + } + else + { + mob_hit(m1,vypocet_zasahu(it->zmeny,m1->vlastnosti,2,fl->damage,fl->hit_bonus)); + mob_hit(m2,vypocet_zasahu(it->zmeny,m1->vlastnosti,2,fl->damage,fl->hit_bonus)); + m1->dir=fl->smer+2&3; + m2->dir=fl->smer+2&3; + } + return 1; + } + else if (map_coord[sector].flags & MC_PLAYER && (fl->owner<=0 || pocet_zivych(sector)>2)) + { + int kolik,i,c=0; + int owner=fl->owner; + + if (it->druh!=TYP_VRHACI) return 1; + if (it->magie) area_cast(it->spell,sector,fl->owner,1); + for(i=0,kolik=0;isektor && p->lives && p->used) + { + char death; + short vlastnosti[VLS_MAX]; + memcpy(vlastnosti,p->vlastnosti,sizeof(vlastnosti)); + if (game_extras & EX_SHIELD_BLOCKING) PodporaStitu(p, vlastnosti); + death=player_hit(p,vypocet_zasahu(it->zmeny,vlastnosti,kolik,fl->damage,fl->hit_bonus),1); + if (death && owner && hlubina_level) mobs[-owner-1].lives=0; //hlubina - nestvura je mrtva + c=1; + } + bott_draw(1); + } + return c; + } + } + else + if (mob_map[sector] && fl->owner>=0) + { + if (fl->owner>=0) select_player=fl->owner-1; + if (it->druh!=TYP_VRHACI) return 1; + mob1=mob_map[sector]-MOB_START;m1=&mobs[mob1]; + mob2=m1->next-MOB_START; + if (mob2>=0) + { + int x1,y1; + m2=&mobs[mob2]; + switch (fl->smer) + { + case 0:x1=fl->ypos;y1=32;break; + case 1:x1=-32;y1=fl->ypos;break; + case 2:x1=-fl->ypos;y1=-32;break; + case 3:x1=32;y1=-fl->ypos;break; + } + if (abs(x1-m1->locx+128)+abs(y1-m1->locy+128)>abs(x1-m2->locx+128)+abs(y1-m2->locy+128)) m1=m2; + } + if (m1->vlajky & MOB_PASSABLE) return 0; + mob_hit(m1,vypocet_zasahu(it->zmeny,m1->vlastnosti,(m2!=NULL)+1,fl->damage,fl->hit_bonus)); + if (it->druh==TYP_VRHACI) fl->flags|=FLY_DESTROY; + if (it->umisteni!=PL_SIP && !(it->flags & ITF_DESTROY)) + { + int i; + for(i=0;iinv[i]==0) { m1->inv[i]=it-glob_items+1;break;} + if (i==MOBS_INV) fl->flags &=FLY_DESTROY; + } + m1->dir=fl->smer+2&3; + return 1; + } + else if (map_coord[sector].flags & MC_PLAYER && (fl->owner<=0 || pocet_zivych(sector)>2)) + { + int kolik,i,j,c=0,r; + int owner=fl->owner; + + if (it->druh!=TYP_VRHACI) return 1;else fl->flags|=FLY_DESTROY; + fl->speed=0; + for(i=0,kolik=0;ivlastnosti,sizeof(vlastnosti)); + if (game_extras & EX_SHIELD_BLOCKING) PodporaStitu(p, vlastnosti);else uprav_podle_kondice(p,&kolik); + death=player_hit(p,vypocet_zasahu(it->zmeny,vlastnosti,kolik,fl->damage,fl->hit_bonus),1); + if (death && owner && hlubina_level) mobs[-owner-1].lives=0; //hlubina - nestvura je mrtva + c=1; + } + bott_draw(1); + } + return c; + } + return 0; + } + +void cast_wait(EVENT_MSG *msg,void **unused) + { + unused; + + if (msg->msg==E_TIMER) + if (!neco_v_pohybu) + { + send_message(E_DONE,E_TIMER,cast_wait); + delete_from_timer(TM_SCENE); + wire_main_functs(); + } + } + +void wire_cast_spell() + { + if (spell_string.action) + { + teleport_target=spell_string.data2; + select_player=caster; + cast(spell_string.data1,&postavy[caster],caster,0); + /*add_to_timer(TM_SCENE,gamespeed,-1,hrat_souboj); + neco_v_pohybu=1; + send_message(E_ADD,E_TIMER,cast_wait);*/ + } + wire_main_functs(); + bott_draw(0); + } + +void wire_fly_casting(int i) + { + if (!postavy[i].used || !postavy[i].lives) return; + magic_data=&spell_string; + memset(&spell_string,0,sizeof(spell_string)); + after_spell_wire=wire_cast_spell; + select_player=i; + wire_select_rune_fly(); + select_player=caster=i; + } + +static void rozdelit_skryte_bonusy(THUMAN *hu) + { + short *vls,*vls2; + short p[]={VLS_SILA,VLS_SMAGIE,VLS_OBRAT}; + short h[3]; + register i; + + vls=hu->vlastnosti; + vls2=hu->stare_vls; + if (vls[p[0]]lives+=h[i];break; + case VLS_SMAGIE: if (vls2[VLS_SMAGIE]) {vls2[VLS_MAXMANA]+=h[i];hu->mana+=h[i];}break; + case VLS_OBRAT: vls2[VLS_KONDIC]+=h[i];hu->kondice+=h[i];break; + } + } + prepocitat_postavu(hu); + } + + +void check_player_new_level(THUMAN *p) + { + int u; + + u=p->level-1; + while (level_map[u]<=p->exp) + { + u++;p->bonus+=5; + rozdelit_skryte_bonusy(p); + prepocitat_postavu(p); + SEND_LOG("(GAME) Character '%s' raised a level %d",p->jmeno,u); + } + p->level=u+1; + } + + +void send_experience(TMOB *p,int dostal) + { + if (select_player<0) return; + if (isdemon(postavy+select_player)) return; + if (p->lives<=0) + { + int i; + for(i=0;ibonus; + check_player_new_level(postavy+i); + } + if (hlubina_level==1) + { + postavy[select_player].lives=0; + player_check_death(postavy+select_player,0); + } + } + if (dostal>0) postavy[select_player].exp+=(long)((float)p->experience*(float)dostal/p->vlastnosti[VLS_MAXHIT]); + check_player_new_level(&postavy[select_player]); + } + + +void send_weapon_skill(int druh) + { + THUMAN *p=&postavy[select_player]; + + if (isdemon(p)) return; + if (p->bonus_zbrani[druh]bonus_zbrani[druh]; + if (c[0]weapon_expy[druh]++; + if (p->weapon_expy[druh]>=weapon_skill[c[0]]) + { + c[0]++; + SEND_LOG("(GAME) Character '%s' raised new weaponskill in '%s'",p->jmeno,texty[91+druh]); + } + } + } + } + +char player_check_death(THUMAN *p, char afterround) + { + p->used&=~0x80; + if (p->lives<=0 && p->groupnum) + if (!battle || afterround) + { + int mp; + int i; + if (isdemon(p)) + { + unaffect_demon(p-postavy); + return 0; + } + for(i=0;iwearing[i]; + if (j) + { + short it[2]; + it[1]=0;it[0]=j;j--; + if (glob_items[j].flags & ITF_NOREMOVE) + { + destroy_items(it); + p->wearing[i]=0; + } + } + } + p->groupnum=0; + p->lives=0; + if (p->level>1) p->exp=level_map[p->level-2]; + p->kondice=0; + p->mana=0; + SEND_LOG("(GAME) Character '%s' died. R.I.P.",p->jmeno,0); + if (numplayers(p->sektor,0)==0) map_coord[p->sektor].flags &=~MC_PLAYER; + mp=map_sectors[p->sektor].sector_type; + if (mp==S_VODA || mp==S_LAVA || mp==S_VIR) p->sektor=0; + else map_coord[p->sektor].flags |= MC_DEAD_PLR; + GlobEvent(MAGLOB_ONDEADMAN+p->female,viewsector,viewdir); + return 1; + } + else + { + if (p->lives<0) p->lives=0; + p->used|=0x80; + } + if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; + return 0; + } + +char mute_hit_sound=0; + +char player_hit(THUMAN *p,int zraneni,char manashield) + { + char check=0; + + if (!p->lives) return check; + if (zraneni>0) + { + THE_TIMER *tt;int h; + + if (zraneni>p->lives) zraneni=p->lives; + p->dostal=zraneni; + if (manashield) manashield_check(p->vlastnosti,&p->lives,&p->mana,p->dostal); //manashield pro hrace + else p->lives-=zraneni; + if (p->female) h=H_SND_HEK1F;else h=H_SND_HEK1M; + h+=rnd(2); + if (!mute_hit_sound) + { + if (GlobEvent(MAGLOB_ONHITMAN+p->female,p->sektor,p->direction)) + play_sample_at_sector(h,p->sektor,viewsector,0,0); + tt=add_to_timer(TM_CLEAR_ZASAHY,100+rnd(100),1,vymaz_zasahy);tt->userdata[0]=p-postavy;tt->userdata[1]=p->dostal; + } + mute_hit_sound=0; + if (immortality) p->lives=p->vlastnosti[VLS_MAXHIT]; + check=player_check_death(p,0); + } + else + { + p->lives-=zraneni; + if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT]; + } + return check; + } + +void enforce_start_battle() + { + if (!battle && see_monster) + { + int i;THUMAN *h; + stop_all_mobs();battle=1; + for(i=0,h=postavy;iused || !h->lives || h->groupnum!=cur_group);i++,h++); + if (i>=POCET_POSTAV) h=postavy,i=0; + att_player=i; + } + } + +void uprav_podle_kondice(THUMAN *p,int *chaos) + { + if (p->kondice<(p->vlastnosti[VLS_POHYB]/2) || p->vlastnosti[VLS_POHYB]<4) + { + *chaos=999; + } + else + p->kondice--; + } + + +void correct_level() + { + THUMAN *h; + int i; + + puts("\x7"); + h=postavy; + for (i=0;iused) + { + int j; + if (h->level>37 || (h->level>1 && h->explevel-2])) + { + poloz_vsechny_predmety(); + picked_item=NewArr(short,2); + picked_item[0]=h->level; + picked_item[1]=0; + pick_set_cursor(); + } + h->level=1; + for (j=0;;j++) if (h->exp>level_map[j]) h->level=j+2;else break; + } + } diff --git a/GAME/SPECPROC.C b/GAME/SPECPROC.C new file mode 100644 index 0000000..1390f67 --- /dev/null +++ b/GAME/SPECPROC.C @@ -0,0 +1,707 @@ +//Toto je hlavni soubor specialnich procedur pro hru BRANY SKELDALU +#include +#include +#include +#include +#include +#include "bgraph.h" +#include "globals.h" +#include "specproc.h" +#include "bmouse.h" +#include +//#include "i86.h" + +#define MOB_GO(m) if (m->dir & 1)m->headx=mob_go_x[m->dir];else m->heady=mob_go_y[m->dir] + +int cur_event_number; + +static void event_error(char *text,int number) + { + char buff[256]; + closemode(); + sprintf(buff,"%s\n Specproc num: %d\n",text,number); + MessageBox(NULL,buff,NULL,MB_OK|MB_ICONSTOP); + exit(1); + } + + +//Item procs--------------------------------------- +ITEM_PROC(item_test) + { + putchar('\x7');event,ptr,p; + putchar('\n'); + return 1; + } + +//Map procs--------------------------------------- +MAP_PROC(map_test) + { + putchar('\x7');sector,side,event,value; + putchar('\n'); + return 1; + } + +void spell_teleport(); +MAP_PROC(map_teleport) + { + side=0;event; + teleport_target=value; + if (mob_map[sector]!=0) + { + int i; + spell_teleport(-mob_map[sector],-1); + if ((i=mobs[mob_map[sector]-1].next)!=0) + spell_teleport(-i,-1); + side=1; + } + if (map_coord[sector].flags & MC_DPLAYER) + { + int i,j=-1;THUMAN *h; + int bit=0; + + for(i=0,h=postavy;iused && h->sektor==sector && h->sektor==viewsector) + { + j=i;break; + } + for(i=0,h=postavy;iused && h->sektor==sector) bit|=1<direction,bit,j!=-1); + side=1; + auto_group(); + } + return side; + } + +/* +static void otoc_obraz1(word *source,word *target) + { + word *p,*q; + word *sp,*sq; + int x,y; + + sp=source+320-180; + sq=target+scr_linelen2*359+320-180; + y=360; + while (y--) + { + p=sp; + q=sq; + x=360; + while (x--) + { + *q=*p; + q-=scr_linelen2; + p++; + } + sp+=scr_linelen2; + sq++; + } + } + +void swap_screen(word *_p,word *_q) + { + __asm + { + mov esi,_p + mov edi,_q + + std + mov ecx,115200 + lp1: + mov ax,[edi] + xchg ax,[esi] + stosw + add esi,2 + dec ecx + jnz lp1 + cld + } + } +// #pragma aux swap_screen parm [esi][edi]=\ modify [ecx eax] + +static void otoc_obraz2(word *source) + { + swap_screen(source,source+scr_linelen2*360-2); + } + +static void otoc_obraz3(word *source,word *target,short smer) + { + word *tt,*ss; + int x,y,xs,ys; + int xp,yp; + + tt=target; + if (smer>0)x=320+126-224;else x=320+126+224; + if (smer>0)y=180-126-224;else y=180+126-224; + yp=360; + ys=0; + while (yp--) + { + xs=0; + ss=source+scr_linelen2*y+x; + xp=640; + while (xp--) + { + if (ss>=source && ss10) + { + xs-=10; + ss+=scr_linelen2+smer; + } + } + ys+=7; + if (ys>10) + if (smer>0) + { + ys-=10; + x--; + y++; + } + else + { + ys-=10; + x--; + y--; + } + } + } + +static void show_liane(THE_TIMER *t) + { + word *bt,*bs; + static int counter=0; + + schovej_mysku(); + if (counter<5 && counter) + { + bt=GetScreenAdr()+SCREEN_OFFSET; + bs=GetBuffer2nd()+SCREEN_OFFSET; + } + else + { + redraw_scene(); + bs=GetScreenAdr()+SCREEN_OFFSET; + } + + switch(counter) + { + case 0:break; + case 1:otoc_obraz3(bs,bt,1);break; + case 2:curcolor=0; + bar(0,SCREEN_OFFLINE,139,SCREEN_OFFLINE+359); + bar(640-140,SCREEN_OFFLINE,639,SCREEN_OFFLINE+359); + otoc_obraz1(bs,bt);break; + case 3:otoc_obraz3(bs,bt,-1);break; + + default:otoc_obraz2(bs);if (counter==4)OutBuffer2nd();break; + } + ukaz_mysku(); + showview(0,0,0,0); + if (!counter) + { + schovej_mysku(); + OutBuffer2nd(); + ukaz_mysku(); + } + if (t->calls==1) + { + THUMAN *h; + int i; + + save_load_trigger((word)(t->userdata[0])); + for(i=0,h=postavy;ilives,0); + h->sektor=0; + } + wire_proc(); + counter=-1; + } + counter++; + } +*/ + + +static const float Inv2=0.5; +static const float Snapper=3<<22; + +static __inline int toInt(float fval) + { + fval += Snapper; + return ( (*(int *)&fval)&0x007fffff ) - 0x00400000; + } + +static void OtocObrazPodleMatice(float mx[3][2], word *picture) + { + word *trg=GetScreenAdr()+17*scr_linelen2; + int x,y; + picture+=6; + for (y=0;y<360;y++,trg+=scr_linelen2) + for (x=0;x<640;x++) + { + int oldx=x-320; + int oldy=y-180; + int newx=toInt(oldx*mx[0][0]+oldy*mx[1][0]+320); + int newy=toInt(oldx*mx[0][1]+oldy*mx[1][1]+180); + if (newx>=0 && newx<640 && newy>=0 && newy<360) + trg[x]=picture[newx+640*newy]; + else + trg[x]=0; + } + } + +static void OtaceniObrazu() + { + word *picture=(word *)malloc(640*360*2+16); + float mx[3][2]; + + int maxtime=500; + int lasttime=GetTickCount(); + int curtime; + get_picture(0,17,640,360,picture); + do + { + float phase; + float uhel; + float cosuhel; + float sinuhel; + curtime=GetTickCount()-lasttime; + phase=curtime/(float)maxtime; + if (phase>1.0f) phase=1.0f; + uhel=phase*3.14159265; + cosuhel=cos(uhel); + sinuhel=sin(uhel); + mx[0][0]=cosuhel; + mx[0][1]=sinuhel; + mx[1][0]=-sinuhel; + mx[1][1]=cosuhel; + OtocObrazPodleMatice(mx,picture); + showview(0,0,0,0); + do_events(); + } + while (curtimeuserdata[0]=save_load_trigger(-1); + schovej_mysku(); + OtaceniObrazu(); + ukaz_mysku(); + for(i=0,h=postavy;ilives,0); + h->sektor=0; + } + redraw_scene(); + cancel_pass=1; + cancel_render=1; + showview(0,0,0,0); + wire_proc(); + return 1; + } +#define ID_XS 400 +#define ID_YS 380 + +MAP_PROC(map_identify) + { + int x,y,yp,xp,ys,yss; + int i,cnt;char s[100]; + TITEM *it; + TSTR_LIST ls; + + sector;side;event;value; + if (picked_item==NULL) return 0; + it=glob_items+*picked_item-1; + ls=create_list(256); + unwire_proc(); + sprintf(s,texty[210],it->jmeno);str_add(&ls,s); + sprintf(s,texty[211],it->hmotnost*2,it->hmotnost>0 && it->hmotnost<3?texty[236]:texty[237]);str_add(&ls,s); + if (it->nosnost) + { + sprintf(s,texty[212],it->nosnost);str_add(&ls,s); + } + for(i=0;i<21;i++) + if (it->zmeny[i] && texty[213+i]!=NULL) + { + if (i==VLS_HPREG || i==VLS_MPREG || i==VLS_VPREG) + sprintf(s,texty[213+i],it->zmeny[i]>0?texty[234]:texty[235]); + else + sprintf(s,texty[213+i],it->zmeny[i],it->zmeny[i+1]); + str_add(&ls,s); + } + if (it->zmeny[VLS_MGSIL_H]) + { + sprintf(s,texty[233],texty[22+it->zmeny[VLS_MGZIVEL]]);str_add(&ls,s); + } + for(i=0;i<16;i++) + if (it->zmeny[VLS_KOUZLA] & (1<0;i--) if (ls[i-1]!=NULL) break; + cnt=i;i=0; + ys=cnt*10+10; + do + { + x=320-ID_XS/2; + y=y=240-ys/2; + create_frame(x,y,ID_XS,ys,1); + xp=x+5;yp=y+5;ys=ID_YS-10; + set_font(H_FBOLD,NOSHADOW(0)); + yss=ys; + while(iuser_data<128 || m->user_data>192) + { + int sector=m->sector; + int i; + TSTENA *side; + + for(i=0,side=map_sides+(sector<<2);i<4;side++,i++) + if (side->flags & SD_MONST_IMPS && side->sector_tag!=0 && (~side->flags & (SD_PASS_ACTION | SD_SECRET))==(SD_PASS_ACTION|SD_SECRET)) + break; + if (i!=4) + { + m->dir=i;stop_mob(m); + if (flag_map[(sector<<2)+i] & SD_MONST_IMPS) a_touch(sector,m->dir); + m->user_data=128; + return 1; + } + side=map_sides+(sector<<2)+((m->dir+2)&3); + if (~side->flags & SD_MONST_IMPS && side->sector_tag!=0 && (~side->flags & (SD_PASS_ACTION | SD_SECRET))==(SD_PASS_ACTION|SD_SECRET)) + { + int ss=map_sectors[sector].step_next[(m->dir+2)&3]; + int j=mob_map[ss]; + while (j) if (mobs[j-1].dir==m->dir) return 0; + else j=mobs[j-1].next; + a_touch(sector,(m->dir+2)&3); + return 0; + } + } + else + { + if (m->user_data>=128 && m->user_data<192) m->user_data++; + if (~map_sides[(m->sector<<2)+m->dir].flags & SD_MONST_IMPS) + { + if (m->dir & 1) m->headx=mob_go_x[m->dir];else m->heady=mob_go_y[m->dir]; + m->user_data=map_coord[map_sectors[m->sector].step_next[m->dir]].flags & MC_PLAYER?255:127; + } + return m->user_data<144; + } + return 0; + } + +MOB_PROC(mob_open_door_battle) + { + if (event==SMPR_ATTACK) + { + m->specproc=5; + } + return 0; + } + +static char spec_proc_test_mob(int event_type,TMOB *m) + { + m,event_type; + putchar('\x7'); + putchar('\n'); + return 0; + } + + +static char mob_dokola(int event_type,TMOB *m) + { + if (event_type==SMPR_WALK) + { + m->dir++; + m->dir &=3; + MOB_GO(m); + return 1; + } + return 0; + } + +static char mob_carodej(int event_type,TMOB *m) + { +static char kouzla[5]={3,8,13,18,80}; + + if (event_type==SMPR_ATTACK) + { + m->casting=kouzla[rnd(5)]; + } + return 0; + } + +static char mob_strelec(int event_type,TMOB *m) + { + if (event_type==SMPR_ATTACK) + { + int i,l; + + if (m->dostal==0 && ~m->user_data & 128) return 0; + for (i=0;i<4;i++) + { + l=map_sectors[m->sector].step_next[i]; + if (l!=0 && map_coord[l].flags & MC_PLAYER) break; + } + if (i==4) + { + if (m->user_data & 128) + { + int s=m->sector; + m->user_data&=~128; + i=m->dir+2&3; + while (s && !(map_coord[s].flags & MC_PLAYER)) if (map_sides[(s<<2)+i].flags & SD_MONST_IMPS) s=0;else s=map_sectors[s].step_next[i]; + if (s) m->dir=i;else return 1; + } + return 0; //strilej + } + i=i+2&3; + if (mob_check_next_sector(m->sector,i,m->stay_strategy & MOB_BIG,0)) + { + int l=4,z,max=RAND_MAX+1; + for(i=0;i<4;i++) + if (!mob_check_next_sector(m->sector,i,m->stay_strategy & MOB_BIG,0)) + { + int s=map_sectors[m->sector].step_next[i]; + if (!get_dangerous_place(s) && (z=rand())dir=i; + MOB_GO(m); + m->user_data|=128; + return 1; + } + else + { + /* + int i,l; + i=m->dir; + l=m->sector; + if (map_sides[(l<<2)+i].flags & SD_MONST_IMPS) return 0; + l=map_sectors[l].step_next[i]; + for(i=0;i<4;i++) + { + int s=map_sectors[l].step_next[i]; + if (isplayer(s,NULL,0)!=NULL) + { + m->dir=i+2&3; + m->headx=mob_go_x[i]; + m->heady=mob_go_y[i]; + return 1; + } + } + */ + if (m->user_data & 128) + { + THUMAN *h; + int i; + + for(i=0,h=postavy;ilives && h->used && + abs(map_coord[h->sektor].x-map_coord[m->sector].x)<2 && + abs(map_coord[h->sektor].y-map_coord[m->sector].y)<2) + { + stop_mob(m); + return 1; + } + } + return 0; //delej si co chces + } + } + + + + +MOB_PROC(mob_krikloun) + { + if (event==SMPR_ATTACK) + { + sirit_zvuk(m->sector); + } + return 0; + } + +static char mob_taktik_recurse(int recall,int sector,int *min_obr,int big,int *csect,int *cdir) + { + int i; + char nasel=0; + + //nejprve zjistime kdo je okolo nas + for(i=0;i<4;i++) + { + int s=map_sectors[sector].step_next[i]; + THUMAN *h=NULL; + + if (!s) continue; //pokud tam je stena tak pokracuj jinym smerem + if (mob_check_next_sector(sector,i,big,0)==1) continue; + if ((h=isplayer(s,h,0))!=NULL) //nekdo tam je - zjisti kdo + while(h!=NULL) + { + if (h->vlastnosti[VLS_OBRAN_H]<*min_obr) // pokud ma nizsi obranu + { + *csect=sector; + *cdir=i; + *min_obr=h->vlastnosti[VLS_OBRAN_H]; + nasel=1; + } + h=isplayer(s,h,0); + } + else if (recall) //pokud tam nikdo neni koukni se vedle + { + if (mob_taktik_recurse(0,s,min_obr,big,csect,cdir)) *cdir=i; + } + } + return nasel; + } + + +MOB_PROC(mob_taktik) + { + int min_obr=1000; + int csect=m->sector; + int cdir=-1; + + if (event==SMPR_ATTACK) + { + mob_taktik_recurse(1,m->sector,&min_obr,m->stay_strategy & MOB_BIG,&csect,&cdir); + if (cdir==-1) return 0; + m->dir=cdir; + if (m->sector!=csect) + { + MOB_GO(m); + return 1; + } + + } + return 0; + } + +MOB_PROC(mob_stoji) + { + if (event==SMPR_ATTACK) + { + int i; + int s; + + for(i=0;i<4;i++) + { + s=map_sectors[m->sector].step_next[i]; + if (s && map_coord[s].flags & MC_PLAYER) return 0; + } + m->headx=m->locx; + m->heady=m->locy; + m->stay_strategy&=~(MOB_WALK | MOB_LISTEN); + m->vlajky&=~MOB_IN_BATTLE; + return 1; + } + else if (event==SMPR_WALK) + { + m->headx=m->locx; + m->heady=m->locy; + } + else if (event==SMPR_KNOCK) return 1; + return 0; + } + +static t_mob_proc sp_mob_table[]= + { + NULL, //0 + spec_proc_test_mob, //1 + mob_dokola, //2 + mob_carodej, //3 + mob_strelec, //4 + mob_open_door, //5 + mob_open_door_battle, //6 + mob_krikloun, //7 + mob_taktik, //8 + mob_stoji, //9 + }; + +#define SP_MOB_TAB_SIZE (sizeof(sp_mob_table)/sizeof(t_mob_proc)) + +static t_item_proc sp_item_table[]= + { + NULL, //0 + item_test, //1 + }; + +#define SP_ITEM_TAB_SIZE (sizeof(sp_item_table)/sizeof(t_item_proc)) + +static t_map_proc sp_map_table[]= + { + NULL, //0 + map_test, //1 + map_teleport, //2 + map_liana, //3 + map_identify, //4 + }; + +#define SP_MAP_TAB_SIZE (sizeof(sp_map_table)/sizeof(t_map_proc)) + +char call_mob_event(int event_number,int event_type,TMOB *m) + { + if (!event_number) return 0; + if (event_number>=SP_MOB_TAB_SIZE) + event_error("Nestv–ra pou‘ˇva neplatnou specproc.",event_number); + cur_event_number=event_number; + return sp_mob_table[event_number](event_type,m); + } + +char call_item_event(int event_number,int event_type,short *ptr,THUMAN *p) + { + if (!event_number) return 0; + if (event_number>=SP_ITEM_TAB_SIZE) + event_error("€ˇslo ud losti u vci je neplatn‚. Specproc nenˇ definov na.",event_number); + cur_event_number=event_number; + return sp_item_table[event_number](event_type,ptr,p); + } + +char call_map_event(int event_number,int sector,int side,int value,int event) + { + if (!event_number) return 0; + if (event_number>=SP_MAP_TAB_SIZE) + event_error("Neplatn‚ ‡ˇslo ud losti na stn. Specproc s tˇmto ‡ˇslem nenˇ definov na.",event_number); + cur_event_number=event_number; + return sp_map_table[event_number](sector,side,value,event); + } + diff --git a/GAME/SPECPROC.H b/GAME/SPECPROC.H new file mode 100644 index 0000000..a8ca9a3 --- /dev/null +++ b/GAME/SPECPROC.H @@ -0,0 +1,39 @@ + + +#define SMPR_WALK 1 +#define SMPR_ATTACK 2 +#define SMPR_KNOCK 3 //povoleni, nebo zakazani KNOCK (zakazani = return 1) + +#define SIPR_USAGE 1 +#define SIPR_PICK 2 +#define SIPR_DROP 3 + + +typedef char (*t_mob_proc)(int event_type,TMOB *); +typedef char (*t_item_proc)(int event_type,short *ptr,THUMAN *p); +typedef char (*t_map_proc)(int sector,int side,int value,int event); + +#define MOB_PROC(name) static char name(int event,TMOB *m) +#define ITEM_PROC(name) static char name(int event,short *ptr,THUMAN *p) +#define MAP_PROC(name) static char name(int sector,int side,int value,int event) + +//specproc pro nestvury vraci char informaci +// 1 - nestvura ma jiz zadanou akci a program se zaridi podle pozadavku specproc +// 0 - specproc ignorovala udalost a nestvura se ma chovat stejne jako bez specproc + +//specproc do mapy +// 1 - specproc uspesna +// 0 - specproc neuspesna +// value - je cislo predavane specproc + + +char call_map_event(int event_number,int sector,int side,int value,int event); +char call_item_event(int event_number,int event_type,short *ptr,THUMAN *p); +char call_mob_event(int event_number,int event_type,TMOB *m); + + +//funkce z enemy.c +char mob_check_next_sector(int sect,int dir,char alone,char passable); + //alone = MOB_BIG, passable= 1 je-li pruchozi +extern char mob_go_x[]; +extern char mob_go_y[]; diff --git a/GAME/TRANSAV.C b/GAME/TRANSAV.C new file mode 100644 index 0000000..009df02 --- /dev/null +++ b/GAME/TRANSAV.C @@ -0,0 +1,682 @@ +#include +#include +#include +#include +#include +#include +#include +#define EVENT_MSG long +#include "globals.h" +#include +#include +#include + +TSTR_LIST skini; + +#define PLAYERS 3 + +void *datablast; +long datablastsize; +char *lasterror=NULL; +char relarr[6]; +char szBuff[65536]; +char sekceid[]=""; + +typedef struct s_save + { + int viewsector; + int viewdir; + int gold; + short cur_group; + char autosave; + char enable_sort; + char shownames; + char showlives; + char zoom_speed; + char turn_speed; + char autoattack; + char music_vol; + char sample_vol; + char xbass; + char bass; + char treble; + char stereing; + char swapchans; + char out_filter; + long glob_flags; + long game_time; + char runes[5]; + char level_name[12]; + short picks; //pocet_sebranych predmetu v mysi + short items_added; //pocet_pridanych predmetu + int sleep_long; + int game_flags; + }S_SAVE; + +typedef struct tkouzlo + { + word num,um,mge; + word pc; + short owner,accnum; //accnum = akumulacni cislo, owner = kdo kouzlo seslal + int start; + short cil; //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) + char povaha; + word backfire; //backfire / 1 = demon , 0 = bez demona + word wait; //wait - cekani pocet animaci + word delay; //delay - cekani pocet kol + char traceon; //jinak noanim - neprehravaji se animace a zvuky + char spellname[30]; + }TKOUZLO; + + +typedef struct _tkzlall + { + TKOUZLO kouzlo; + short vlstab[24]; + long flagmap; + }TKZLALL; + +THUMAN postavy[6],postavy2[6]; +S_SAVE s; +char mapname[13]; +int startsect; +int startsid; + + +char cz_table_1[]=" 1!3457­908+,-./‚+¨‡©‘ ˇ\"–?=:_2ABCDEFGHIJKLMNOPQRSTUVWXYZŁ\\)6=;abcdefghijklmnopqrstuvwxyz/|(; "; +char cz_table_2[]=" !\"#$%&'()*+,-./0123456789:;<=>?@ŹBCDFGH‹JKŠMN•PQ«ST—VWXťZ[\\]^_` bcd‚fghˇjkŤmn˘pqŞstŁvwxz{|}~ "; +char cz_table_3[]=" !\"#$%&'()*+,-./0123456789:;<=>?@AB€…‰FGHIJKśMĄ§PQž›†¦VWXY’[\\]^_`ab‡fghijkŚm¤“pq©¨ź–vwxy‘{|}~ "; +char *cz_key_tabs[]={cz_table_1,cz_table_2,cz_table_3}; + +word keyconv(word key) + { + int i; + static char cz_mode=0; + char c,d; + + i=key; + d=i>>8; + c=i & 0xff; + if (c=='+' && d<55 && !cz_mode) cz_mode=2; + else if (c=='=' && d<55 && !cz_mode) cz_mode=1; + else if (c>32 && c<127 && d<=53) + { + c=cz_key_tabs[cz_mode][c-32]; + i=d; + i=(i<<8)+c; + cz_mode=0; + return i; + } + else + return i; + + return 0; + } + + +#define ZAKLAD_CRC 0xC005 + +static word vypocet_crc(char *data,long delka) + { + unsigned long l=0; + do + { + l=(l<<8)|(delka>0?*data++:0);delka--; + l=(l<<8)|(delka>0?*data++:0);delka--; + l%=ZAKLAD_CRC; + } + while(delka>-1); + return l & 0xffff; + } + +static simple_cz_input(char *buff,int maxchars) + { + int cnt=strlen(buff); + int w; + char *a; + a=alloca(cnt+1); + strcpy(a,buff); + maxchars--; + cputs(buff); + do + { + w=_bios_keybrd(_KEYBRD_READ); + w=keyconv(w); + if (w==0) continue; + switch (w & 0xff) + { + case 13: return; + case 0x8: if (cnt>0) + { + cnt--;buff[cnt]=0;cputs("\x8 \x8"); + } + break; + case 0:break; + case 27:strcpy(buff,a); + return; + default: if (cntkouzlo.cil-1; + + if (kzl->kouzlo.cil>0) + { + for (j=0;j<22;j++) h->stare_vls[j]+=kzl->vlstab[j]; + h->stare_vls[VLS_KOUZLA]&=~(kzl->flagmap & 0xffff); + } + } + } + +void zero_inv(THUMAN *h) + { + h->inv_size=6; + memset(h->inv,0,sizeof(h->inv)); + memset(h->wearing,0,sizeof(h->wearing)); + memset(h->prsteny,0,sizeof(h->prsteny)); + memcpy(h->vlastnosti,h->stare_vls,sizeof(h->vlastnosti)); + h->demon_save=NULL; + h->sektor=startsect; + h->direction=startsid; + h->groupnum=1; + } + + +void zero_all_inv() + { + THUMAN *h=postavy;int i; + + for (i=0;i<6;i++,h++) if (h->used) zero_inv(h); + } + +void unpack_save(void *in) + { + int kouzel; + TKZLALL *kzl; + int i; + + in=loadmem(&s,in,sizeof(s)); //load basic info + in=(void *)((char *)in+s.picks*2+s.items_added*sizeof(TITEM)); //skip items; + in=loadmem(&kouzel,in,sizeof(kouzel)); //load spell table + kzl=in; //signup spell table for future use + in=(void *)((char *)in+sizeof(TKZLALL)*kouzel); + in=loadmem(postavy,in,sizeof(postavy)); //load character table + for (i=0;i<6;i++) + if (postavy[i].demon_save!=NULL) //correct demons; + in=loadmem(postavy+i,in,sizeof(THUMAN)); + //skip dialog info. + //load done; + return_spells(kouzel,kzl); + zero_all_inv(); + s.viewsector=startsect; + s.viewdir=startsid; + s.picks=0; + s.items_added=0; + s.glob_flags=0; + s.game_time=0; + strncpy(s.level_name,mapname,12); + memset(s.runes,0,sizeof(s.runes)); + } + +void del_character(char c) + { + int i; + for(i=c;i<5;i++) relarr[i]=relarr[i+1]; + relarr[i]=0; + } + +void add_character(char c) + { + THUMAN *h=postavy+c; + int i; + + if (!h->used) + { + lasterror="Musis vybrat postavu!";return; + } + for (i=0;i<6;i++) if (relarr[i]==c+1) + { + del_character(i);return; + } + for (i=0;i<6;i++) if (!relarr[i]) break; + if (i==6) + { + lasterror="Nevim sice jak se ti to povedlo, ale neni uz misto!";return; + } + relarr[i]=c+1; + } + +char nvlast[][16]= + {"Sila","Schopnost magie","Pohyblivost","Obratnost","Max zraneni", + "Kondice","Max mana","Obrana(dolni)","Obrana(Horni)","Utok(Dolni)", + "Utok(Horni)","Ohen","Voda","Zeme","Vzduch","Mysl","Zivoty Regen", + "Mana Regen","Kondice Regen","Magicka sila(D)", "Magicka sila(H)","","Ucinnek zasahu","*"}; + +char *zbrane[]={"Mec","Sekera","Kladivo","Hul","Dyka","Strelne","Specialni"}; + + +char build_players() + { + int i; + char z=0; + + memset(postavy2,0,sizeof(postavy2)); + for (i=0;i<6;i++) + if (relarr[i])postavy2[i]=postavy[relarr[i]-1],z=1; + return z; + } + +void c_info(int b) + { + THUMAN *h=postavy+b; + int i; + + do + { + _clearscreen(_GCLEARSCREEN); + for(i=0;i<22;i++) + { + cprintf("%-17s %3d ",nvlast[i],h->stare_vls[i]); + if (i<7) + cprintf("%-12s %3d ",zbrane[i],h->bonus_zbrani[i]); + if (i<7) + switch (i) + { + case 0: cprintf("Jmeno: %s",h->jmeno);break; + case 1: cprintf("Uroven: %d",h->level);break; + case 2: cprintf("Zkusenost: %d",h->exp);break; + case 3: cprintf("Pohlavi: %s",h->female?"Zena":"Muz");break; + case 4: cprintf("Portret: XICHT%02X.PCX",h->xicht);break; + case 5: cprintf("Jidlo: %d",h->jidlo/360);break; + case 6: cprintf("Voda: %d",h->voda/360);break; + } + cprintf("\n\r"); + } + cprintf("ENTER - zmena jmena, P - pohlavi, X - vzhledu, ESC - navrat:"); + do + {i=toupper(getche());putch(8);} + while (i!=13 && i!='X' && i!=27 && i!='P'); + if (i==13) + { + cprintf("\r\n\n Zmen jmeno:");simple_cz_input(h->jmeno,sizeof(h->jmeno)); + } + else if (i=='X') + { + cprintf("\r\n\n Jelikoz jednoduchost tohoto programu neumoznuje prohizet si obrazky je nutne\n\r" + "tuto volbu odzkouset metodou pokus omyl. Nikdo totiz nezaruci, zda v novem \n\r" + "dobrodruzstvi se nektere z postav nezmeni pohlavi (na obrazku).\r\n" + "V puvodnim SKELDALU:\n\r" + "--------------------\n\r" + "Muzi: 0, 2, 3, 4, 8(Roland), 12(Gralt), 13(Erik)\n\r" + "Zeny: 1, 5, 6, 7\n\r" + "\nZmenit vzhled <%d>, 'x' storno:",h->xicht); + if (scanf("%hd",&h->xicht)==0) while (getchar()!='\n'); + } + else if (i=='P') h->female=!h->female; + } + while (i!=27) ; + } + + +char assign_players() + { + int i; + char c; + char backrel[6]; + + do + { + _clearscreen(_GCLEARSCREEN); + if (lasterror!=NULL) cprintf("%s\x7\r\n\n",lasterror); + lasterror=NULL; + memset(backrel,0,sizeof(backrel)); + for (i=0;i<6;i++) if (relarr[i]) backrel[relarr[i]-1]=i+1; + cprintf("%-33s%s\n\r====================================================\n\r","Stare dobrodruzstvi","Nove dobrodruzstvi"); + for(i=0;i<6;i++) + { + if (postavy[i].used) + cprintf("%c%d.%-30s",backrel[i]?'*':' ',i+1,postavy[i].jmeno); + else + cprintf(" %d.%-30s",i+1,""); + if (relarr[i]) + cprintf("%c.%-30s",i+'a',postavy[relarr[i]-1].jmeno); + else + cprintf("%c.%-30s",i+'a',""); + cputs("\n\r"); + } + cputs("\n\r"); + cputs("[1]-[6] prenese postavu,\n\r" + "[a]-[f] maze postavu.\n\r" + "[SHIFT]+[1]-[6] info o postave\n\r" + "[S] ulozit\n\r" + "[Q] nebo [ESC] konec bez ulozeni\n\n\r"); + cprintf("Doporuceny pocet postav v novem dobrodruzstvi je %d.\n\r",PLAYERS); + putch('>'); + i=_bios_keybrd(_KEYBRD_READ); + c=toupper(i & 0xff);i>>=8; + switch (c) + { + case 27: + case 'Q':return 1; + case 'S':return 0; + default: + if (i==0) lasterror="Prepni na anglickou klavesnici!!!"; + if (i>=2 && i<=7) + if (*(char *)0x417 & 0x3) c_info(i-2); + else add_character(i-2); + if (c>='A' && c<='F') del_character(c-'A'); + break; + } + } + while(1); + } + +char *scan_saves(char *text,char *path,char mustexists) + { + int i; + FILE *f; + + do + { + _clearscreen(_GCLEARSCREEN); + cprintf("%s\n\r============================\n\r",text); + if (lasterror!=NULL) cprintf("%s\x7\r\n\n",lasterror); + lasterror=NULL; + for(i=0;i<10;i++) + { + sprintf(szBuff,"%sSLOT%02d.SAV",path,i); + cprintf("%d. ",(i+1)%10); + f=fopen(szBuff,"rb"); + if (f!=NULL) + { + fread(szBuff,1,34,f);szBuff[34]=0; + fclose(f); + cprintf("%s\r\n",szBuff); + } + else + cputs("\r\n"); + } + cputs("\nVyber [1]-[9] a [0] pozici.\n\r[ESC] zrusit.\n\r"); + do + i=_bios_keybrd(_KEYBRD_READ)>>8; + while (i>11); + if (i==1) return NULL; + if (i==0) lasterror="Prepni na anglickou klavesnici!!!"; + else + { + i-=2; + sprintf(szBuff,"%sSLOT%02d.SAV",path,i); + if (!mustexists || access(szBuff,F_OK)==0) return szBuff; + } + } + while(1); + } + +int tracemap(char *name) + { + FILE *f; + void *section; + int type; + long size,s; + + f=fopen(name,"rb"); + if (f==NULL) return -1; + do + { + s=load_section(f,§ion,&type,&size); + if (s!=size) + { + free(section); + fclose(f); + return -1; + } + if (type==A_MAPGLOB) + { + MAPGLOBAL mglob; + memcpy(&mglob,section,sizeof(mglob)); + startsect=mglob.start_sector; + startsid=mglob.direction; + } + free(section); + } + while (type!=A_MAPEND); + fclose(f); + return 0; + } + +void *build_gametmp(int *size) + { + int siz=*size; + void *zac,*p; + int i,crc; + + siz+=256; + p=zac=malloc(siz); + p=addmem(p,&s,sizeof(s)); //add game info + //skip picks + //skip items added + i=0;//no spells; + p=addmem(p,&i,4); + p=addmem(p,postavy2,sizeof(postavy2)); + p=addmem(p,&i,4); //no dialogs... + *size=(char *)p-(char *)zac; + crc=vypocet_crc(zac,*size); + p=addmem(p,&crc,2); + size[0]+=2; + return zac; + } + +void save_savegame(char *soubor) + { + FILE *f; + void *p; + int s; + + f=fopen(soubor,"wb"); + strcpy(szBuff,"TRANSAV"); + fwrite(szBuff,SAVE_NAME_SIZE,1,f); + strcpy(szBuff,"_GAME.TMP"); + fwrite(szBuff,12,1,f); + s=datablastsize; + p=build_gametmp(&s); + fwrite(&s,4,1,f); + fwrite(p,s,1,f); + free(p); + szBuff[0]=0; + fwrite(szBuff,12,1,f); + fclose(f); + } + +void begin_program(char *sourceadv,char *targetadv) + { + TSTR_LIST src,trg; + char *c; + + src=read_config(sourceadv); + if (src==NULL) + { + cprintf("Nemohu otevrit zdrojove dobrodruzstvi: %s\n\r",sourceadv); + exit(1); + } + trg=read_config(targetadv); + if (trg==NULL) + { + cprintf("Nemohu otevrit cilove dobrodruzstvi: %s\n\r",targetadv); + exit(1); + } + c=get_text_field(trg,"DEFAULT_MAP"); + if (c==NULL) + { + cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku DEFAULT_MAP\n\r", targetadv); + exit(1); + } + strncpy(mapname,c,12);mapname[12]=0; + c=get_text_field(trg,"CESTA_MAPY"); + if (c==NULL) + { + cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku CESTA_MAPY\n\r", targetadv); + exit(1); + } + sprintf(szBuff,"%s%s",c,mapname); + if (tracemap(szBuff)) + { + cprintf("Nemohu precist mapu %s\n\r",szBuff); + exit(1); + } + c=get_text_field(trg,"CESTA_POZICE"); + if (c==NULL) + { + cprintf("Vystupni dobrodruzstvi %s musi obsahovat polozku CESTA_POZICE\n\r", targetadv); + exit(1); + } + c=get_text_field(src,"CESTA_POZICE"); + if (c==NULL) + { + cprintf("Vstupni dobrodruzstvi %s musi obsahovat polozku CESTA_POZICE\n\r", sourceadv); + exit(1); + } + c=scan_saves("Vyber pozici:",c,1); + if (c==NULL) exit(0); + load_specific_file(c,"_GAME.TMP",&datablast,&datablastsize); + if (datablast==NULL) + { + cprintf("Soubor %s: Pristup odmitnut - pozice je pozkozena!\n\r",c); + exit(1); + } + unpack_save(datablast); + do + { + do + if (assign_players()) exit(1); + while (!build_players()); + zpet: + c=get_text_field(trg,"CESTA_POZICE"); + c=scan_saves("Ulozit na pozici:",c,0); + } + while (c==NULL); + if (access(c,F_OK)==0) + { + cprintf("Prejes si prepsat existujici pozici? (A/cokoliv):"); + if (toupper(getche())!='A') goto zpet; + } + save_savegame(c); + } + +static char help1[]= + "Tento program prenasi ulozene pozice mezi jednotlivymi dobrodruzstvimi.\n\r" + "Jelikoz ulozena pozice je znacne zavisla na mapach a definicich, je mozne\n\r" + "timto programem prenaset pouze charakteristiky postav. Navic se mohou \n\r" + "objevit nejake komplikace vznikle s nemoznosti predvidat komplexnost obou\n\r" + "dobrodruzstvi.\n\r\n" + "Program ma dva zapisy parametru:\n\r" + "================================\n\r\n" + "TRANSAV \n\r\n" + " Prenasi puvodni pozici ze hry Brany Skeldalu do noveho dobrodruzstvi\n\r\n" + "TRANSAV \n\r\n" + " Prenasi pozici mezi dvema dobrodruzstvi\n\r\n"; +static char help2[]= + "Jak uz bylo receno, prenasi se pouze charakteristiky postav. Neprenasi se\n\r" + "predmety a runy. Nova pozice se jmenuje TRANSAV, pak si ji prejmenujte. \n\r" + "Ihned po nahrati prenesene pozice okamzite tuto pozici opet ulozte, aby SKELDAL\n\r" + "doplnil chybejici informace vztahujici se k novemu dobrodruzstvi. \n\r" + "V pokrocilejsich castech hry mohou tyto chybejici informace zpusobovat nejake\n\r" + "komplikace...\n\r\n" + "Prenasec pozic pro Vas napsal Ondrej Novak, programator hry Brany Skeldalu.\n\r\n" + "PS: Deaktivujte ovladace ceske klavesnice!!!\n\r"; + +void main(int argc,char **argv) + { + char szbuff[20]; + + if (argc!=2 && argc!=3) + { + cputs(help1); + cputs("--- klavesu ---");getche();putch('\r'); + cputs(help2); + return; + } + memset(relarr,0,sizeof(relarr)); + if (argc==2) + begin_program("SKELDAL.INI",argv[1]); + else + begin_program(argv[1],argv[2]); + } + + + + + diff --git a/GAME/WIZARD.C b/GAME/WIZARD.C new file mode 100644 index 0000000..afbf429 --- /dev/null +++ b/GAME/WIZARD.C @@ -0,0 +1,758 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.h" +#include +#include + +void kamenik2windows(const char *src, int size, char *trg); + +#define BREAK + +static HWND hWizardDlg=NULL; +static HWND hWizardText; +static HFONT hfCourier; + +static void wzprintf(const char *text,...) + { + int len=GetWindowTextLength(hWizardText); + char *c=(char *)alloca(len+1024); + char *d; + va_list args; + + GetWindowText(hWizardText,c,len+1024); + if (len>10000) c+=1024; + d=strchr(c,0); + va_start(args,text); + _vsnprintf(d,1020,text,args); + SetWindowText(hWizardText,c); + len=strlen(c); + SendMessage(hWizardText,EM_SETSEL,len,len); + SendMessage(hWizardText,EM_SCROLLCARET,0,0); + } + +static void wzputs(const char *text) + { + wzprintf(text); + wzprintf("\r\n"); + } + +static void wzcls() + { + SetWindowText(hWizardText,""); + } + +static LRESULT InputWindow(HWND hDlg,UINT msg, WPARAM wParam,LPARAM lParam) + { + static char *buff; + switch (msg) + { + case WM_INITDIALOG: + buff=(char *)lParam; + SetDlgItemText(hDlg,IDC_PROMPT,buff); + hDlg=GetWindow(hDlg,GW_OWNER); + EnableWindow(hDlg,TRUE); + return 0; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCANCEL: EndDialog(hDlg,0);break; + case IDOK: + GetDlgItemText(hDlg,IDC_VALUE,buff,1020); + EndDialog(hDlg,1); + break; + } + break; + default: return 0; + } + return 1; + } + +static LRESULT CALLBACK ListWindow(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: PostQuitMessage(LOWORD(wParam));break; + case IDC_LIST: if (HIWORD(wParam)==LBN_DBLCLK) PostQuitMessage(IDOK);break; + default: return 0; + } + default: return 0; + } + return 1; +} + +static HWND PrepareListWindow(HWND parent) +{ + HWND res; + RECT rc1,rc2; + GetWindowRect(parent,&rc1); + EnableWindow(parent,0); + res=CreateDialog(GetModuleHandle(0),MAKEINTRESOURCE(IDD_LISTDIALOG),parent,(DLGPROC)ListWindow); + GetWindowRect(res,&rc2); + rc2.right=rc2.right-rc2.left; + rc2.bottom=rc2.bottom-rc2.top; + rc2.left=(rc1.left+rc1.right-rc2.right)/2; + rc2.top=(rc1.top+rc1.bottom-rc2.right)/2; + SetWindowPos(res,0,rc2.left,rc2.top,rc2.right,rc2.bottom,SWP_NOZORDER); + ShowWindow(res,SW_SHOW); + + return res; +} + +static void CloseListWindow(HWND wnd) +{ + HWND parent=GetParent(wnd); + DestroyWindow(wnd); + EnableWindow(parent,1); +} + +static int PumpDialogMessages(HWND dlg) +{ + MSG msg; + while (GetMessage(&msg,0,0,0)) + { + if (!IsDialogMessage(dlg,&msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return msg.wParam; +} + + +static int wzscanf(const char *prompt, const char *format,...) + { + char buff[1024]; + va_list args; + unsigned long data[10]; + int i; + + static char notallowed=0; + + if (notallowed) return 0; + notallowed=1; + + strcpy(buff,prompt); + if (DialogBoxParam(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_INPUTWINDOW),GetActiveWindow(),(DLGPROC)InputWindow,(LPARAM)buff)==0) + { + notallowed=0; + return 0; + } + + notallowed=0; + + va_start(args,format); + for (i=0;i<10;i++) data[i]=va_arg(args,unsigned long); + return sscanf(buff,format,data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9]); + } + +char *side_flags[]= + { + "AUTOMAP", + "!PLR", + "!MONST", + "!THING", + "!SOUND", + "ALARM", + "PASS", + "TRANSPARENT", + "P_ANIM", + "P_VIS", + "P_PING", + "P_FORW", + "S_ANIM", + "S_VIS", + "S_PING", + "S_FORW", + "LEFT_A", + "RIGHT_A", + "ALT_SIDES", + "SPEC", + "COPY", + "SEND", + "APLY2ND", + "AUTOANIM", + "", + "", + "", + "", + "", + "SECRET", + "TRUESEE", + "INVIS" + }; + +char *obl_flags[]= + { + "RECESS", + "UP_SIDE", + "DOWN_SIDE", + "ITPUSH" + }; + +char *mc_flags[]= + { + "MAPPED", + "FLY_OBJECT", + "PLAYER", + "DEAD_PLAYER", + "SPECTXTR", + "SAFEPLACE", + "UNUSED", + "MARKED!", + "SHADED", + "STAIRS", + "DOWN", + "!AUTOMAP", + "!SUMMON" + }; + +void mman_scan(int action) + { + extern char screenstate; + static pos=0,zavora=0; + MEMORYSTATUS mmi; + char c[10]; + if (screenstate && !zavora) + { + zavora=1; + switch(action) + { + case MMA_SWAP:curcolor=RGB555(31,0,0);break; + case MMA_READ:curcolor=RGB555(0,31,0);break; + case MMA_SWAP_READ:curcolor=RGB555(0,0,31);break; + case MMA_FREE:curcolor=RGB555(31,31,31);break; + } + bar(pos,0,pos+16,16); + get_mem_info(&mmi); + set_font(H_FBOLD,RGB555(31,31,31)); + curcolor=0; + bar(16,0,66,16); + position(16,0);sprintf(c,"%d",mmi.dwAvailPageFile/1024); + outtext(c); + showview(pos,0,66,16); + zavora=0; + } + } + +void show_flags(int number,char **flags,char nums) + { + int i=0; + while (nums--) + { + if (number & 1) wzprintf("%s ",flags[i]); + i++; + number>>=1; + } + } + +void spell_group_invis() + { + int i; + char ok=1; + + for(i=0;ijidlo/MAX_HLAD(human_selected); + mv=(float)human_selected->voda/MAX_ZIZEN(human_selected); + human_selected=h; + h->exp=level_map[level-2]; + check_player_new_level(h); + if (auto_advance) + { + int vlssuma=h->vlastnosti[VLS_SILA]+ + h->vlastnosti[VLS_OBRAT]+ + h->vlastnosti[VLS_POHYB]+ + h->vlastnosti[VLS_SMAGIE]; + int b,i; + + for(i=0;i<4;i++) + { + b=h->vlastnosti[i]*h->bonus/vlssuma; + h->bonus-=b;vlssuma-=h->vlastnosti[i]; + while (b--) advance_vls(i); + } + prepocitat_postavu(human_selected); + } + human_selected->jidlo=(int)(mh*MAX_HLAD(human_selected)); + human_selected->voda=(int)(mv*MAX_ZIZEN(human_selected)); + wzprintf("%s ziskal%s uroven cislo %d\r\n",h->jmeno,h->female?"a":"",level); + } + + +extern char folow_mode; +extern char folow_mob; +void macro_drop_item(); + +static char take_money() + { + int i; + if (!wzscanf("Kolik: (0 - zrusit):","%d",&i)) return 0; + money+=i; + if (i) + { + SEND_LOG("(WIZARD) Take Money %d, total %d",i,money); + } + return (i!=0); + } + +#define ALL "ALL" +static char purge_map() + { + char buffer[200]; + char *c; + + STOP(); +/* struct find_t rc; + int rs; + + concat(c,pathtable[SR_TEMP],"*.TMP"); + rs=_dos_findfirst(c,_A_NORMAL,&rc); + while (rs==0) + { + if (rc.name[0]!='~') wzputs(rc.name); + rs=_dos_findnext(&rc); + } + _dos_findclose(&rc);*/ + wzprintf("\r\n Zadej jmeno tempu (all - vse):");gets(buffer); + if (buffer[0]==0) return 0; + strupr(buffer); + concat(c,pathtable[SR_TEMP],buffer); + if (strcmp(buffer,ALL) && access(c,0)) + { + wzputs("Soubor nenalezen!"); + return 0; + } + SEND_LOG("(WIZARD) Purge Map: '%s'",buffer,0); + if (!strcmp(buffer,ALL)) purge_temps(0); + else remove(c); + return 1; + } + +static char heal_meditate(void) + { + int a,b,i; + THUMAN *p; + + if (!wzscanf("Obnovit postavu c: (0 - vsechny, -1 - zrusit):","%d",&b)) return 0; + if (b==-1) return 0; + if (b) a=b-1;else a=0,b=POCET_POSTAV; + p=postavy+a; + for(i=a;iused && p->lives) + { + p->lives=p->vlastnosti[VLS_MAXHIT]; + p->mana=p->vlastnosti[VLS_MAXMANA]; + p->kondice=p->vlastnosti[VLS_KONDIC]; + p->jidlo=MAX_HLAD(p); + p->voda=MAX_ZIZEN(p); + SEND_LOG("(WIZARD) Restoring character '%s'",p->jmeno,0); + bott_draw(1); + } + return 1; + } + +static char raise_death(void) + { + int b; + THUMAN *p; + char *c,*d; + + if (!wzscanf("Obzivit postavu c: (0 a -1 - zrusit):","%d",&b)) return 0; + b--; + if (b<0) return 0; + p=postavy+b; + p->lives=p->vlastnosti[VLS_MAXHIT]; + p->mana=p->vlastnosti[VLS_MAXMANA]; + p->kondice=p->vlastnosti[VLS_KONDIC]; + c="(WIZARD) '%s' has been returned to game by gods power!";d=strchr(c,'\''); + wzprintf(d,p->jmeno);putchar('\r\n'); + bott_draw(1); + return 0; + } + + static char raise_killed_monster(HWND hDlg) + { + HWND listdlg=PrepareListWindow(hDlg); + HWND list=GetDlgItem(listdlg,IDC_LIST); + char buff[256]; + int i; + int res; + + for (i=0;ibonus_zbrani[i],h->weapon_expy[i]); + if (!wzscanf(" ","%[^\n]",buff)) return 0; + if (buff[0]==0) return 0; + if (sscanf(buff,"%d %d",&bonus,&value)!=2) wzputs("Huh?!"); + else + { + bonus--; + if (bonus<0 || bonus>=TPW_MAX) wzputs("Spatna zbran"); + else + if (value<0 || value>=10) wzputs("Spatna hodnota"); + else + h->bonus_zbrani[bonus]=value; + } + } + while(1); + } + +static reload_mobs() + { + extern char reset_mobiles; + reset_mobiles=1; + strncpy(loadlevel.name,level_fname,12); + loadlevel.start_pos=viewsector; + loadlevel.name[12]=0; + loadlevel.dir=viewdir; + send_message(E_CLOSE_MAP); + } + +static char display_game_status(void) + { + short *v; + THUMAN *p; + TSTENA *s; + TSECTOR *ss; + register i,cn,astr; + + wzcls(); + SEND_LOG("(WIZARD) Starting wizard window at Sect %d Side %d",viewsector,viewdir); + wzprintf("Sektor: %5d Smer: %d Skupina %d \r\n",viewsector,viewdir,cur_group); + for(i=0,p=postavy;iused) + wzprintf("%d.%-14s (%d) Sek:%5d Smr:%d HPReg:%d MPReg:%d VPReg:%d %04X%s\r\n",i+1,p->jmeno,p->groupnum,p->sektor,p->direction,p->vlastnosti[VLS_HPREG], + p->vlastnosti[VLS_MPREG], p->vlastnosti[VLS_VPREG], p->vlastnosti[VLS_KOUZLA], p->lives?"":"(smrt)"); + else + wzprintf("%d. (nepouzito)\r\n",i); + wzputs(""); + wzprintf("Predmet(y) v mysi: "); + v=picked_item; + if (v==NULL) wzprintf("");else while(*v) wzprintf("%d ",abs(*v++)-1); + wzputs("\r\n"); + for(i=0,cn=0,astr=0;isector_type, ss->floor,ss->ceil,ss->sector_tag,ss->side_tag,ss->action); + wzprintf(" Vychody: Sev %d Vych %d Jih %d Z p %d\r\n",ss->step_next[0],ss->step_next[1],ss->step_next[2],ss->step_next[3]); + wzprintf(" Vlajky: %02X %02X ",ss->flags,map_coord[viewsector].flags);show_flags(map_coord[viewsector].flags,mc_flags,12); + wzputs("\r\n"); + wzprintf("Stena: Prim %d Sec %d Obl %d Anim_prim %d/%d Anim_sec %d/%d\r\n", + s->prim,s->sec,s->oblouk & 0xf,s->prim_anim>>4,s->prim_anim & 0xf,s->sec_anim>>4,s->sec_anim & 0xf); + wzprintf(" Cil akce %d Smer akce %d Akce %d\r\n",s->action,s->sector_tag,s->side_tag & 0x3); + wzprintf(" Multiakce: %s\r\n",macros[viewsector*4+viewdir]==NULL?"":"Existuje"); + wzprintf(" Vlajky: %04X %02X %02X ",s->flags,s->oblouk>>4,s->side_tag>>2); + wzputs(""); + show_flags(s->flags,side_flags,32); + show_flags(s->oblouk>>4,obl_flags,4); + return 0; + } + +static LRESULT WizardDlgProc(HWND hDlg,UINT msg, WPARAM wParam,LPARAM lParam) + { + int i; + switch (msg) + { + case WM_INITDIALOG: + hWizardDlg=hDlg; + hWizardText=GetDlgItem(hDlg,IDC_OUTPUT); + SendMessage(hWizardText,WM_SETFONT,(WPARAM)hfCourier,1); + display_game_status(); + SetTimer(hDlg,10,20,NULL); + return 0; + case WM_TIMER: do_events();return 1; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCANCEL: EndDialog(hDlg,0);return 0; + case IDC_CLEARMAP: + { + HWND listwnd=PrepareListWindow(hDlg); + HWND list=GetDlgItem(listwnd,IDC_LIST); + int res; + ListBox_AddString(list,"Clear Monsters"); + ListBox_AddString(list,"Clear Items"); + res=PumpDialogMessages(listwnd); + if (res==IDOK) + { + if (ListBox_GetSel(list,0)) + { + for(i=0;i:","%d %d",&i,&j)) return 0; + c=MessageBox(GetActiveWindow(),"Automaticky?","?",MB_YESNO|MB_ICONQUESTION); + if (i>0) advence_player(i-1,j,c==IDYES);else + for(i=0;i:",mapsize-1); + if (!wzscanf(prompt,"%d",&viewsector)) return 0; + chod_s_postavama(1); + SEND_LOG("(WIZARD) Goto %d",viewsector,0); + return 0; + } + case IDC_LOADMAP: + if (!wzscanf("Load Map ","%s %hd",loadlevel.name,&loadlevel.start_pos)) return 0; + for(i=0;imsg==E_KEYBOARD) + { + c=(*(int *)msg->data)>>8; + msg->msg=-1; + switch (c) + { + case 'C': + case 'D': + unwire_proc(); + OpenWizard(); + wire_proc(); + showview(0,0,0,0); + break; + case '<':show_debug=!show_debug;break; + case '=':show_lives=!show_lives;break; + case '>':if (mman_action!=NULL) mman_action=NULL;else mman_action=mman_scan;break; + case '@':set_immortality();set_nohassle();break; + case 'A':bott_draw_fletna();break; + case 'B':wire_global_map();break; + case '?':cur_group=10;break;/*folow_mode=!folow_mode; + if (folow_mode) folow_mob=mob_map[map_sectors[viewsector].step_next[viewdir]]-1; + else for(c=0;cmsg=E_KEYBOARD;break; + + } + } + return; + } + +void install_wizard() + { + send_message(E_ADD,E_KEYBOARD,wizard_kbd); + } + + + diff --git a/GAME/WIZARD.H b/GAME/WIZARD.H new file mode 100644 index 0000000..718a3b5 --- /dev/null +++ b/GAME/WIZARD.H @@ -0,0 +1 @@ +void install_wizard(); diff --git a/GAME/engine2.c b/GAME/engine2.c new file mode 100644 index 0000000..6e3777c --- /dev/null +++ b/GAME/engine2.c @@ -0,0 +1,1315 @@ +#include +#include "types.h" +#include "Engine1.h" +#include + + +typedef ZOOMINFO tzoom; + +extern ZOOMINFO zoom; +extern word *screen; + +void sikma_zleva(void) +{ + + word *scr = (word *)zoom.startptr; + const word *palette = (word *)zoom.palette; + word cy = zoom.ycount; + const unsigned char *pixmap = zoom.texture; + const short *ytable = zoom.ytable; + while (cy) { + const long *xtable = zoom.xtable; + word cx = zoom.xmax; + word *scr_iter = scr; + const unsigned char *pixmap_iter = pixmap; + while (cx > 0) { + unsigned char pb = *pixmap_iter++; + pixmap_iter+=*xtable; + xtable++; + if (pb == 1) break; + if (pb != 0) *scr_iter = palette[pb]; + scr_iter++; + cx--; + } + pixmap+=zoom.texture_line*(*ytable); + ytable++; + scr-=scr_linelen2; + cy--; + } + + + + /* + + + __asm + { + mov edi,zoom ;nacti ukazatel do obrazovky + mov ebx,[zoom]tzoom.palette ;ukazatel na paletu + mov cx,short ptr [zoom]tzoom.ycount ;velikost textury na y + shl ecx,16 ;vloz do horni pulky ecx + mov esi,[zoom]tzoom.texture ;nacti ukazatel na texturu + skzl3: mov edx,[zoom]tzoom.xtable ;nacti ukazetel na zvetsovaci tabulku x + push esi ;uchovej esi + push edi ;uchovej edi + mov cx,[zoom]tzoom.xmax + skzl1: xor eax,eax ;vynuluj eax pro spravny vypocet + lodsb ;nacti bod + add esi,[edx] ;posun se od nekolik pozic v texture podle hodnoty v tabulce x + add edx,4 ;posun se v tabulce x o dalsi polozku + or al,al ;test bodu na nulu + jz skz1 ;preskoc transparetni barvu + cmp al,1 ;test bodu na jedna + jz skz2 ;ukonci kresleni linky pokud narazi na 1 + mov ax,[eax*2+ebx] ;konverze barvy podle palety + mov [edi],ax ;nakresli bod na obrazovce + skz1: add edi,2 ;dalsi pozice + dec cx + jnz skzl1 ;opakuj dokola + skz2: pop edi ;obnov edi + pop esi ;obnov esi + mov edx,[zoom]tzoom.ytable ;vyzvedni ukazatel na ytable + mov cx,[edx] ;cx - o kolik pozic se mam v texture posunout dolu + or cx,cx + jz skzskp + skzl2: add esi,[zoom]tzoom.texture_line ;posun o jednu pozici + dec cx ;sniz citac + jnz skzl2 ;dokud neni nula + skzskp:add edx,2 ;dalsi hodnota v tabulce + mov [zoom]tzoom.ytable,edx ;uloaz na puvodni misto + sub edi,[zoom]tzoom.line_len ;odecti tolik, kolik odpovida lince na obrazovce + sub ecx,10000h ;sniz horni pulku ecx o jedna + jnz skzl3 ;opakuj dokud neni nula + }*/ +} + +void sikma_zprava(void) +{ + + word *scr = (word *)zoom.startptr; + const word *palette = (word *)zoom.palette; + word cy = zoom.ycount; + const unsigned char *pixmap = zoom.texture; + const short *ytable = zoom.ytable; + while (cy) { + const long *xtable = zoom.xtable; + word cx = zoom.xmax; + word *scr_iter = scr; + const unsigned char *pixmap_iter = pixmap; + while (cx > 0) { + unsigned char pb = *pixmap_iter++; + pixmap_iter+=*xtable; + xtable++; + if (pb == 1) break; + if (pb != 0) *scr_iter = palette[pb]; + scr_iter--; + cx--; + } + pixmap+=zoom.texture_line*(*ytable); + ytable++; + scr-=scr_linelen2; + cy--; + } +/* + __asm + { + mov edi,zoom ;nacti ukazatel do obrazovky + mov ebx,[zoom]tzoom.palette ;ukazatel na paletu + mov cx,short ptr [zoom]tzoom.ycount ;velikost textury na y + shl ecx,16 ;vloz do horni pulky ecx + mov esi,[zoom]tzoom.texture ;nacti ukazatel na texturu +skzp3: mov edx,[zoom]tzoom.xtable ;nacti ukazetel na zvetsovaci tabulku x + push esi ;uchovej esi + push edi ;uchovej edi + mov cx,[zoom]tzoom.xmax +skzp1: xor eax,eax ;vynuluj eax pro spravny vypocet + lodsb ;nacti bod + add esi,[edx] ;posun se od nekolik pozic v texture podle hodnoty v tabulce x + add edx,4 ;posun se v tabulce x o dalsi polozku + or al,al ;test bodu na nulu + jz skz3 ;preskoc transparetni barvu + cmp al,1 ;test bodu na jedna + jz skz4 ;ukonci kresleni linky pokud narazi na 1 + mov ax,[eax*2+ebx] ;konverze barvy podle palety + mov [edi],ax ;nakresli bod na obrazovce +skz3: sub edi,2 ;dalsi pozice + dec cx + jnz skzp1 ;opakuj dokola +skz4: pop edi ;obnov edi + pop esi ;obnov esi + mov edx,[zoom]tzoom.ytable ;vyzvedni ukazatel na ytable + mov cx,[edx] ;cx - o kolik pozic se mam v texture posunout dolu + or cx,cx + jz skpskp +skzp2: add esi,[zoom]tzoom.texture_line ;posun o jednu pozici + dec cx ;sniz citac + jnz skzp2 ;dokud neni nula +skpskp: add edx,2 ;dalsi hodnota v tabulce + mov [zoom]tzoom.ytable,edx ;uloaz na puvodni misto + sub edi,[zoom]tzoom.line_len ;odecti tolik, kolik odpovida lince na obrazovce + sub ecx,10000h ;sniz horni pulku ecx o jedna + jnz skzp3 ;opakuj dokud neni nula + }*/ +} + + +void fcdraw(void *source,void *target, void *table) +//#pragma aux fcdraw parm [EDX][EBX][EAX] modify [ECX ESI EDI]; +{ + + word *src = (word *)source; + word *trg = (word *)target; + T_FLOOR_MAP *t = (T_FLOOR_MAP *)table; + unsigned long cc; + + do { + word *ss = t->txtrofs/2+src; + word *tt = t->lineofs/2+trg; + cc = t->linesize; + memcpy(tt,ss,cc*2); + cc = t->counter; + t++; + } while (cc != 0); +/* + __asm + { + mov edx,source + mov ebx,target + mov eax,table + ;Kresli strop nebo podlahu podle draw_table + ;EDX - sourceTxt + ;EBX - TargerTxt - LineOfset + ; (Lineofs je pocet bajtu odpovidajici + ; souradnicim [0,184] pro podlahu nebo [0,0] + ; pro strop) + ;EAX - draw_table +fcdraw_:mov esi,[eax+12] + mov edi,[eax] + add edi,ebx + add esi,edx + mov ecx,[eax+4] + shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,[eax+8] + add eax,16 + or ecx,ecx + jnz fcdraw_ + }*/ +} + +void klicovani_anm_back(void *target,void *source); +void klicovani_anm(void *target,void *source,char mirror) +//#pragma aux klicovani_anm parm [edi][esi][eax] modify [ecx edx ebx] +{ + word *t = (word *)target; + word *s = (word *)source; + if (mirror) { + unsigned int l = 180; + while (l > 0) { + unsigned int c = 640; + while (c > 0) { + word p = *s++; + if ((p & 0x8000 ) == 0) { + p = p + (p & ~0x1F); + --c; + t[c] = p; + t[c+scr_linelen2] = p; + --c; + t[c] = p; + t[c+scr_linelen2] = p; + } else { + c-=2; + } + } + t+=2*scr_linelen2; + --l; + } + } else { + + unsigned int l = 180; + while (l > 0) { + unsigned int c = 320; + while (c > 0) { + word p = *s++; + if ((p & 0x8000 ) == 0) { + p = p + (p & ~0x1F); + t[0] = p; + t[scr_linelen2] = p; + ++t; + t[0] = p; + t[scr_linelen2] = p; + ++t; + } else { + t+=2; + } + --c; + } + t+=scr_linelen2; + --l; + } + + } +} + /* + __asm + { + mov edi,target + mov esi,source + + mov cl,180 +ka_lp2: mov ebx,320 +ka_lp1: lodsw + movzx eax,ax + test eax,0x8000 + jnz ka_skip + mov edx,eax + and edx,0x7FE0 + add eax,edx + mov edx,eax + shl edx,16 + add edi,scr_linelen + or eax,edx + mov [edi],eax + sub edi,scr_linelen + mov [edi],eax +ka_skip:add edi,4 + dec ebx + jnz ka_lp1 + sub edi,1280 + add edi,scr_linelen + add edi,scr_linelen + dec cl + jnz ka_lp2 + } +} + +static void klicovani_anm_back(void *target,void *source) +//#pragma aux klicovani_anm parm [edi][esi][eax] modify [ecx edx ebx] +{ + __asm + { + mov edi,target + mov esi,source + + mov ecx,180 + add edi,1280 +kba_lp2: mov ebx,320 +kba_lp1: lodsw + sub edi,4 + movzx eax,ax + test eax,0x8000 + jnz kba_skip + mov edx,eax + and edx,0x7FE0 + add eax,edx + mov edx,eax + shl edx,16 + add edi,scr_linelen + or eax,edx + mov [edi],eax + sub edi,scr_linelen + mov [edi],eax +kba_skip:dec ebx + jnz kba_lp1 + add edi,scr_linelen + add edi,scr_linelen + add edi,1280 + dec ecx + jnz kba_lp2 + } +} +*/ + +#define zobraz_1 \ + __asm lodsb \ + __asm movzx eax,al \ + __asm movzx eax,short ptr [eax*2+ebx] \ + __asm stosw \ + + + +void small_anm_buff(void *target,void *buff,void *paleta) +//#pragma aux small_anm_buff parm[edi][esi][ebx] modify [eax ecx] +{ + word *t = (word *)target; + unsigned char *s = (unsigned char *)buff; + word *p = (word *)paleta; + int i,j; + + for ( i = 0; i < 180; i++) { + for (j = 0; j < 320; j++) { + *t++ = p[*s++]; + } + t+=scr_linelen2-320; + } +/* + __asm + { + mov edi,target; + mov esi,buff; + mov ebx,paleta + + mov ecx,179*10000h +shmab4: mov cx,320 +shmab3: zobraz_1 + dec cx + jnz shmab3 + add edi,640 + sub ecx,010000h + jnc shmab4 + }*/ +} + +void small_anm_delta(void *target,void *buff,void *paleta) +//#pragma aux small_anm_delta parm[edi][esi][ebx] modify [eax ecx] +{ + word *t = (word *)target; + word *pal = (word *)paleta; + unsigned long *deltastart = (unsigned long *)buff; + unsigned long ofs = *deltastart++; + unsigned char *control = (unsigned char *)deltastart; + unsigned char *pixels = control + ofs; + int y; + + for (y = 0; y < 180; y++) { + word *tp = t; + do { + unsigned char c = *control++; + if (c >= 0xc0) { + //skip line + unsigned char d = c - 0xc0; + y+=d; + t+=(d+1)*scr_linelen2; + break; + } else { + tp+=2*c; + c = *control++; + while (c) { + *tp++ = pal[*pixels++]; + *tp++ = pal[*pixels++]; + c--; + } + } + } while (1); + } +} + +/* + + __asm + { + mov edi,target; + mov esi,buff; + mov ebx,paleta + + + mov ch,180 ;180 radek + mov eax,[esi] ;vem offset na delta data + lea edx,[esi+eax+4] ;ebp obsahuje tento offset + lea esi,[esi+4] ;esi obsahuje offset na delta control +shmad5: push edi ;uchovej zacatek radky +shmad3: lodsb ;vem skip hodnotu + mov ah,al ;uchovej ji ah - kvuli destruktivnimu testu + and al,not 3fh ;na posledni 2 bity + cmp al,0c0h ;C0 a vyssi znamenaji ze se preskakuje radek + jz shmad1 ;pri pozitivnim testu je preskoc + movzx eax,ah ;vem skip hodnotu do eax + shl eax,2 ;na obrazovce *2 bodu *1 zoom *2 za bod (x4) + add edi,eax ;pricti k edi + lodsb ;vem copy hodnotu + mov cl,al ;zaved counter + xchg esi,edx ;prohod ukazatele control a data +shmad2: zobraz_1 ;zobraz bod + zobraz_1 ;zobraz bod + dec cl ;opakuj tolikrat kolik je copy hodnota + jnz shmad2 + xchg esi,edx ;prohod ukazatele control a data + jmp shmad3 ;a precti dalsi skip hodnotu +shmad1: pop edi + and ah,03fh ;maskuj spodnich 6 bitu + inc ah ;+1 +shmad4: add edi,scr_linelen + dec ch ;odecti counter radek + dec ah ;odecti counter + jnz shmad4 ;a opakuj ah krat + or ch,ch ;je li counter nulovy tak padame + jnz shmad5 + }*/ + + + +void scroll_and_copy(void *pic,void *slide, void *scr, int _size,int shift, void *lineinfo) +//#pragma aux scroll_and_copy parm[esi][ebx][edi][ecx][edx][eax] +{ + + word *srcpc = (word *)pic; + word *trg = (word *)scr; + word *sld = (word *)slide; + int shiftofs = shift*scr_linelen2; + int lc = _size; + int *lnfo = (int *)lineinfo; + int y; + + for (y = 0; y < lc; y++ ) { + int left = __min(lnfo[0],lnfo[2]); + int right = __max(lnfo[1],lnfo[3]); + int x; + for (x = left; x <= right; x++) { + + word c = sld[x] = sld[x+shiftofs]; + if (c & BGSWITCHBIT) { + trg[x] = srcpc[x]; + } else { + trg[x] = c; + } + } + sld+=scr_linelen2; + trg+=scr_linelen2; + srcpc+=scr_linelen2; + lnfo+=2; + + + } +/* + + + __asm + { + mov esi,pic + mov ebx,slide + mov edi,scr + mov ecx,_size + mov edx,shift + mov eax,lineinfo + ;odscroluje a kopiruje obrazovku do screenu + ;pouzitelne pro titulky + ;0x8000 je transparentni + ;edi screen + ;ebx buffer + ;esi back_picture + ;ecx velikost bufferu (pocet_radku) + ;edx pocet bajtu o kolik je nutne posouvat (*1280) + ;eax - ukazatel na tittle lines + push ebp + mov ebp,eax ;uloz ukazatel na titlelines + mov eax,edx + imul eax,scr_linelen +sac_lp1:push ecx + push eax + mov eax,[ebp] ;nacti zac + mov ecx,[ebp+edx*8] + cmp eax,ecx + jc sac_sk1 + mov eax,ecx +sac_sk1:shl eax,1 ;adresa + add esi,eax ;pricti k pointrum + add edi,eax + add ebx,eax + add ebp,4 ;presun se na kon + shr eax,1 ;eax je zacatek v bodech + mov ecx,[ebp+edx*8] ;vem konec + cmp ecx,[ebp] + jnc sac_sk2 + mov ecx,[ebp] +sac_sk2:push ecx + sub ecx,eax ;kon-zac+1=celk pocet + xchg edx,[esp+4] +sac_lp2:mov eax,[ebx+edx] ;Vem data na dalsim radku + mov [ebx],eax ;Zapis je sem + add ebx,4 ;dalsi pozice + test eax,~BGSWITCHBIT ;je to transparentni? + jz sac_all ;pokud ano, zobraz_obrazek + bt eax,5 ;test bitu 15 + jnc sac_1 ;Neni nastaven - zobraz primo barvu + mov ax,[esi] ;jinak vem barvu z obrazku +sac_1: stosw ;zapis barvu + add esi,2 ;dalsi pozice + rol eax,16 ;presun eax na dolni slovo + bt eax,5 ;test bitu 15 + jnc sac_2 ;neni nastaven - zobraz primo barvu + mov ax,[esi] ;jinak vem barvu z obrazku +sac_2: stosw ;zapis barvu + add esi,2 ;dalsi pozice + jmp sac_end +sac_all:movsd ;presun celeho slova +sac_end:sub ecx,2 ;odecti counter + ja sac_lp2 ;je li nad opakuj + add ecx,640 ;pricti sirku, - kolik jsme prejeli + pop eax + sub ecx,eax ;odecti konec -> kolik preskocit + add ebp,4 ;aktualizuj ukazatele + shl ecx,1 ;v adresach + add esi,ecx + push edx + mov edx,scr_linelen + sub edx,1280 + add ecx,edx + add edi,ecx + add ebx,ecx + pop edx + pop eax + xchg edx,eax + pop ecx ;obnov ecx + dec ecx ;sniz citac radku + jnz sac_lp1 ;dokud neni nula + pop ebp ;obnov ebp + + } + */ +} + +#define pic_start 2+2+2+512*5+512*5 +#define ed_stack 800*4+600*4 +#define ed_stk1 600*4 + + +void enemy_draw(void *src,void *trg,int shade,int scale,int maxspace,int clip) +//#pragma aux enemy_draw parm[ESI][EDI][EBX][EDX][EAX][ECX] +{ + word *picinfo = (word *)src; + word *screen = (word *)trg; + int xtable[800]; + int ytable[1200]; + int xcount; + int ycount; + word pcx = picinfo[0]; + word pcy = picinfo[1]; + unsigned char *picdata = (unsigned char *)src + pic_start; + word *palette = picinfo+shade/2; + int clipl = clip & 0xFFFF; + int clipr = clip >> 16; + int yiter; + + if (maxspace >= 470) return; + + //prepare ytable; + { + int rwofs = pcx*(pcy-1); + int accu = 0; + int *w = ytable; + int sp = maxspace*2; + + while (sp > 0 && rwofs >= 0) { + *w++ = rwofs; + accu+=320; + while (accu >= scale && rwofs >= 0) { + accu-=scale; + rwofs-=pcx; + } + sp--; + } + ycount = w - ytable; + *w++=-1; + //ytable je hotova - obsahuje ofsety v obrazku pro kazdou radku a na konci je -1 + } + + //prepare xtable + { + int *w = xtable; + int ofs = 0; + int accu = 0; + while (ofs < pcx) { + *w++ = ofs; + accu+=320; + while (accu >= scale) { + accu-=scale; + ofs++; + } + } + xcount = w - xtable; + *w++=-1; + //xtable je hotova - obsahuje offset v obrazku pro kazdy sloupec a na konci je -1 + } + + if (clipl > xcount) return; + yiter = 0; + while (ytable[yiter] >= 0) { + int xiter = clipl; + int ofs = ytable[yiter]; + unsigned char *row = picdata+ofs; + while (xiter < clipr && xtable[xiter] >= 0 ) { + int xpos = xiter; + unsigned char p = row[xtable[xiter]]; + if (p != 0) { + if (p == 1) screen[xpos] = (screen[xpos] & 0xF7DE) >> 1; + else screen[xpos] = palette[p]; + } + ++xiter; + } + + screen-=scr_linelen2; + ++yiter; + } + +/* + + __asm + { + mov esi,src + mov edi,trg + mov ebx,shade + mov edx,scale + mov eax,maxspace + mov ecx,clip + + cmp eax,470 + jc ed_ok1 + ret +ed_ok1: push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,short ptr[esi] ;precti xs + movzx eax,short ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +ed_lp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +ed_lp1a:cmp ebp,edx + jc ed_nxt1 ;pri ebp=velikosti obrazku tak konec + jc ed_lp2a + xor eax,eax + dec eax ;zapis -1 na konec tabulky + pop ebx ; +2 + stosd + mov eax,edi ;konecnou pozici pro tabulku x zapis do eax + pop edi ;obnov registry edi exc ebx+1 + add ebx,esi ;najdi adresu prekladove tabulky barev + add ebx,2 ;preskoc transparentni barvu + add esi,pic_start;presun se na zacatek obrazku + pop ecx ; +0 + movzx edx,cx ;vem levy okraj + lea edx,[ebp+edx*4] + lea edx,[edx+ed_stk1];edx ukazuje na sloupce + cmp eax,edx ;je-li levy okraj za platnou tabulkou tak konec + jbe ed_err + shr ecx,16 ;ecx ted obsahuje pravy okraj +ed_lp4: push esi ;uchovej esi +1 + push edi ;uchovej edi +2 + add esi,[ebp] ;spocitej spravnou hodnotu esi + push ecx ;uchovej pravy okraj +3 + push edx ;uchovej ukazatel na tabulku+4 +ed_lp3: mov eax,[edx] + cmp eax,-1 ;testuj konec tabulky + jz ed_end3 ;pri pozitivnim vysledku => konec radky + movzx eax,byte ptr[esi+eax];vem barvu + or al,al + jz ed_skp1 ;preskoc transparentni barvu + dec al + jz ed_shd ;1=shadow + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp ed_skp2 +ed_shd: movzx eax,short ptr[edi];vem barvu + and eax,0xF7DE ;stmav + shr eax,1 + stosw ;zapis + jmp ed_skp2 ;skok na konec +ed_skp1:add edi,2 ;preskoc bod +ed_skp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz ed_lp3 +ed_end3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,scr_linelen ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz ed_lp4 ;jinak pokracuj +ed_err: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + } + */ +} +void enemy_draw_transp(void *src,void *trg,void *shade,int scale,int maxspace,int clip) +//#pragma aux enemy_draw_transp parm[ESI][EDI][EBX][EDX][EAX][ECX] +{ + + word *picinfo = (word *)src; + word *screen = (word *)trg; + int xtable[800]; + int ytable[1200]; + int xcount; + int ycount; + word pcx = picinfo[0]; + word pcy = picinfo[1]; + word type = picinfo[2]; + unsigned char *picdata = (unsigned char *)src+(type == (512+8)?6:pic_start); + word *palette = (word *)shade; + int clipl = clip & 0xFFFF; + int clipr = clip >> 16; + int yiter; + + if (maxspace >= 470) return; + + //prepare ytable; + { + int rwofs = pcx*(pcy-1); + int accu = 0; + int *w = ytable; + int sp = maxspace*2; + + while (sp > 0 && rwofs >= 0) { + *w++ = rwofs; + accu+=320; + while (accu >= scale && rwofs >= 0) { + accu-=scale; + rwofs-=pcx; + } + sp--; + } + ycount = w - ytable; + *w++=-1; + //ytable je hotova - obsahuje ofsety v obrazku pro kazdou radku a na konci je -1 + } + + //prepare xtable + { + int *w = xtable; + int ofs = 0; + int accu = 0; + while (ofs < pcx) { + *w++ = ofs; + accu+=320; + while (accu >= scale) { + accu-=scale; + ofs++; + } + } + xcount = w - xtable; + *w++=-1; + //xtable je hotova - obsahuje offset v obrazku pro kazdy sloupec a na konci je -1 + } + + if (clipl > xcount) return; + yiter = 0; + while (ytable[yiter] >= 0) { + int xiter = clipl; + int ofs = ytable[yiter]; + unsigned char *row = picdata+ofs; + while (xiter < clipr && xtable[xiter] >= 0 ) { + int xpos = xiter -clipl; + unsigned char p = row[xtable[xiter]]; + if (p != 0) { + if (p & 0x80) screen[xpos] = ((screen[xpos] & 0xF7DE) + (palette[p] & 0xF7DE))>>1; + else screen[xpos] = palette[p]; + } + ++xiter; + } + + screen-=scr_linelen2; + ++yiter; + } + +/* __asm + { + mov esi,src + mov edi,trg + mov ebx,shade + mov edx,scale + mov eax,maxspace + mov ecx,clip + + cmp eax,470 + jc et_ok1 + ret +et_ok1: push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,short ptr[esi] ;precti xs + movzx eax,short ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +et_lp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +et_lp1a:cmp ebp,edx + jc et_nxt1 ;pri ebp=velikosti obrazku tak konec + jc et_lp2a + xor eax,eax + dec eax ;zapis -1 na konec tabulky + pop ebx ; +2 + stosd + mov eax,edi ;konecnou pozici pro tabulku x zapis do eax + pop edi ;obnov registry edi exc ebx+1 + cmp byte ptr [esi+5],2 ;obrazek bez palety? + jz et_pl1 + add esi,pic_start;presun se na zacatek obrazku (za paletu) + jmp et_pl2 +et_pl1: add esi,6 ;(obrazek bez palety, presun se za hlavicku) +et_pl2: pop ecx ; +0 + movzx edx,cx ;vem levy okraj + lea edx,[ebp+edx*4] + lea edx,[edx+ed_stk1];edx ukazuje na sloupce + cmp eax,edx ;je-li levy okraj za platnou tabulkou tak konec + jbe et_err + shr ecx,16 ;ecx ted obsahuje pravy okraj +et_lp4: push esi ;uchovej esi +1 + push edi ;uchovej edi +2 + add esi,[ebp] ;spocitej spravnou hodnotu esi + push ecx ;uchovej pravy okraj +3 + push edx ;uchovej ukazatel na tabulku+4 +et_lp3: mov eax,[edx] + cmp eax,-1 ;testuj konec tabulky + jz et_end3 ;pri pozitivnim vysledku => konec radky + movzx eax,byte ptr[esi+eax];vem barvu + test al,80h + jnz et_shd + or al,al + jz et_skp1 ;preskoc transparentni barvu + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp et_skp2 +et_shd: and short ptr[edi],0xF7DE ;1111 0111 1101 1110 + mov eax,[ebx+eax*2];vyzvedni hicolor + and eax,0xF7DE ;stmav + add ax,short ptr[edi] + rcr ax,1 + stosw ;zapis + jmp et_skp2 ;skok na konec +et_skp1:add edi,2 ;preskoc bod +et_skp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz et_lp3 +et_end3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,scr_linelen ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz et_lp4 ;jinak pokracuj +et_err: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + }*/ +} + +void enemy_draw_mirror_transp(void *src,void *trg,void *shade,int scale,int maxspace,int clip) +//#pragma aux enemy_draw_mirror_transp parm[ESI][EDI][EBX][EDX][EAX][ECX] +{ + + word *picinfo = (word *)src; + word *screen = (word *)trg; + int xtable[800]; + int ytable[1200]; + int xcount; + int ycount; + word pcx = picinfo[0]; + word pcy = picinfo[1]; + word type = picinfo[2]; + unsigned char *picdata = (unsigned char *)src+(type == (512+8)?6:pic_start); + word *palette = (word *)shade; + int clipl = clip & 0xFFFF; + int clipr = clip >> 16; + int yiter; + + if (maxspace >= 470) return; + + //prepare ytable; + { + int rwofs = pcx*(pcy-1); + int accu = 0; + int *w = ytable; + int sp = maxspace*2; + + while (sp > 0 && rwofs >= 0) { + *w++ = rwofs; + accu+=320; + while (accu >= scale && rwofs >= 0) { + accu-=scale; + rwofs-=pcx; + } + sp--; + } + ycount = w - ytable; + *w++=-1; + //ytable je hotova - obsahuje ofsety v obrazku pro kazdou radku a na konci je -1 + } + + //prepare xtable + { + int *w = xtable; + int ofs = pcx-1; + int accu = 0; + while (ofs >= 0) { + *w++ = ofs; + accu+=320; + while (accu >= scale) { + accu-=scale; + ofs--; + } + } + xcount = w - xtable; + *w++=-1; + //xtable je hotova - obsahuje offset v obrazku pro kazdy sloupec a na konci je -1 + } + + if (clipl > xcount) return; + yiter = 0; + while (ytable[yiter] >= 0) { + int xiter = clipl; + int ofs = ytable[yiter]; + unsigned char *row = picdata+ofs; + while (xiter < clipr && xtable[xiter] >= 0 ) { + int xpos = xiter -clipl; + unsigned char p = row[xtable[xiter]]; + if (p != 0) { + if (p & 0x80) screen[xpos] = ((screen[xpos] & 0xF7DE) + (palette[p] & 0xF7DE))>>1; + else screen[xpos] = palette[p]; + } + ++xiter; + } + + screen-=scr_linelen2; + ++yiter; + } + + /* + __asm + { + mov esi,src + mov edi,trg + mov ebx,shade + mov edx,scale + mov eax,maxspace + mov ecx,clip + + push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,short ptr[esi] ;precti xs + movzx eax,short ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +etmlp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +etmlp1a:cmp ebp,edx + jc etmnxt1 ;pri ebp konec radky + movzx eax,byte ptr[esi+eax];vem barvu + test al,80h + jnz etmshd + or al,al + jz etmskp1 ;preskoc transparentni barvu + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp etmskp2 +etmshd: and short ptr[edi],0xF7DE + mov eax,[ebx+eax*2];vyzvedni hicolor + and eax,0xF7DE ;stmav + add ax,short ptr[edi] + rcr ax,1 + stosw ;zapis + jmp etmskp2 ;skok na konec +etmskp1:add edi,2 ;preskoc bod +etmskp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz etmlp3 +etmend3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,scr_linelen ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz etmlp4 ;jinak pokracuj +etmerr: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + } + */ +} +void enemy_draw_mirror(void *src,void *trg,int shade,int scale,int maxspace,int clip) +//#pragma aux enemy_draw_mirror parm[ESI][EDI][EBX][EDX][EAX][ECX] +//clip je v poradi vpravo - vlevo (HiLo) +{ + word *picinfo = (word *)src; + word *screen = (word *)trg; + int xtable[800]; + int ytable[1200]; + int xcount; + int ycount; + word pcx = picinfo[0]; + word pcy = picinfo[1]; + unsigned char *picdata = (unsigned char *)src + pic_start; + word *palette = picinfo+shade/2; + int clipl = clip & 0xFFFF; + int clipr = clip >> 16; + int yiter; + + if (maxspace >= 470) return; + + //prepare ytable; + { + int rwofs = pcx*(pcy-1); + int accu = 0; + int *w = ytable; + int sp = maxspace*2; + + while (sp > 0 && rwofs >= 0) { + *w++ = rwofs; + accu+=320; + while (accu >= scale && rwofs >= 0) { + accu-=scale; + rwofs-=pcx; + } + sp--; + } + ycount = w - ytable; + *w++=-1; + //ytable je hotova - obsahuje ofsety v obrazku pro kazdou radku a na konci je -1 + } + + //prepare xtable + { + int *w = xtable; + int ofs = pcx-1; + int accu = 0; + while (ofs >= 0) { + *w++ = ofs; + accu+=320; + while (accu >= scale) { + accu-=scale; + ofs--; + } + } + xcount = w - xtable; + *w++=-1; + //xtable je hotova - obsahuje offset v obrazku pro kazdy sloupec a na konci je -1 + } + + if (clipl > xcount) return; + yiter = 0; + while (ytable[yiter] >= 0) { + int xiter = clipl; + int ofs = ytable[yiter]; + unsigned char *row = picdata+ofs; + while (xiter < clipr && xtable[xiter] >= 0 ) { + int xpos = xiter; + unsigned char p = row[xtable[xiter]]; + if (p != 0) { + if (p == 1) screen[xpos] = (screen[xpos] & 0xF7DE) >> 1; + else screen[xpos] = palette[p]; + } + ++xiter; + } + + screen-=scr_linelen2; + ++yiter; + } + + /* + + __asm + { + mov esi,src + mov edi,trg + mov ebx,shade + mov edx,scale + mov eax,maxspace + mov ecx,clip + + push ebp + sub esp,ed_stack ;vyhrad zasobnik + mov ebp,esp + push ecx ;uchovej ecx +1 + push edi ;uchovej edi +2 + push ebx ;uchovej ebx +3 + mov ebx,eax ;volne misto je ted v ebx + mov edi,ebp ;nastav edi na zacatek tabulek + push ebp ; +4 + movzx ecx,short ptr[esi] ;precti xs + movzx eax,short ptr[esi+2] ;precti ys + imul eax,ecx ;xs*ys + sub eax,ecx ;minus 1 radek + xor ebp,ebp +edmlp1b:stosd ;zapis hodnotu do tabulky + add ebp,320 ;zmensovani +edmlp1a:cmp ebp,edx + jc edmnxt1 ;pri ebp konec radky + movzx eax,byte ptr[esi+eax];vem barvu + or al,al + jz edmskp1 ;preskoc transparentni barvu + dec al + jz edmshd ;1=shadow + mov eax,[ebx+eax*2];vyzvedni hicolor + stosw ;zapis barvu + jmp edmskp2 +edmshd: movzx eax,short ptr[edi];vem barvu + and eax,0xF7DE ;stmav + shr eax,1 + stosw ;zapis + jmp edmskp2 ;skok na konec +edmskp1:add edi,2 ;preskoc bod +edmskp2:add edx,4 ;dalsi pozice + dec ecx ;dokud nedosahneme praveho okraje obrazku + jnz edmlp3 +edmend3:pop edx ;obnov vse ulozene + pop ecx + pop edi + pop esi ; +0 + add ebp,4 ;dalsi y souradnice + sub edi,scr_linelen ;dalsi radka + cmp dword ptr [ebp],-1 ;test na konec tabulky + jnz edmlp4 ;jinak pokracuj +edmerr: add esp,ed_stack;vymaz tabulku + pop ebp ;obnov ebp + } + */ +} \ No newline at end of file diff --git a/GAME/extras.h b/GAME/extras.h new file mode 100644 index 0000000..6b9393b --- /dev/null +++ b/GAME/extras.h @@ -0,0 +1,16 @@ +#define EX_RANDOM_BACKFIRES 1 //hotovo +#define EX_RESPAWN_MONSTERS 2 //hotovo +#define EX_ALTERNATEFIGHT 4 //hotovo +#define EX_RECOVER_DESTROYED_ITEMS 8 //hotovo +#define EX_MULTIPLE_ITEMS_IN_CURSOR 16 //zruseno +#define EX_BAG_EXTENDED 32 //hotovo +#define EX_SHIELD_BLOCKING 64 //hotovo +#define EX_FAST_TRADE 128 //hotovo +#define EX_ALWAYS_MINIMAP 256 //hotovo +#define EX_GROUP_FLEE 512 +#define EX_NOHUNGRY 1024 +#define EX_AUTOOPENBOOK 2048 +#define EX_AUTOSHOWRUNE 4096 +#define EX_WALKDIAGONAL 8192 + +extern int game_extras; \ No newline at end of file diff --git a/GAME/version.h b/GAME/version.h new file mode 100644 index 0000000..50623c8 --- /dev/null +++ b/GAME/version.h @@ -0,0 +1,13 @@ +#define VERSION_MAJOR 1 +#define VERSION_MAJORT "1" +#define VERSION_MINOR 2 +#define VERSION_MINORT "2" +#define VERSION_BUILD 17 +#define VERSION_BUILDT "17" + + +#define VERSION VERSION_MAJORT"."VERSION_MINORT" Build "VERSION_BUILDT +#define VERSIONNUM VERSION_MAJOR*1000000+VERSION_MINOR*10000+VERSION_BUILD +#define VERSIONWINSTR VERSION_MAJORT","VERSION_MINORT","0","VERSION_BUILDT +#define VERSIONWINRES(x) x VERSION_MAJOR, VERSION_MINOR, 0, VERSION_BUILD + diff --git a/GIF/Decoder.c b/GIF/Decoder.c new file mode 100644 index 0000000..617b530 --- /dev/null +++ b/GIF/Decoder.c @@ -0,0 +1,377 @@ +/* DECODE.C - An LZW decoder for GIF + * Copyright (C) 1987, by Steven A. Bennett + * + * Permission is given by the author to freely redistribute and include + * this code in any program as long as this credit is given where due. + * + * In accordance with the above, I want to credit Steve Wilhite who wrote + * the code which this is heavily inspired by... + * + * GIF and 'Graphics Interchange Format' are trademarks (tm) of + * Compuserve, Incorporated, an H&R Block Company. + * + * Release Notes: This file contains a decoder routine for GIF images + * which is similar, structurally, to the original routine by Steve Wilhite. + * It is, however, somewhat noticably faster in most cases. + * + */ + +#include +#include "std.h" +#include "errs.h" + +IMPORT TEXT *malloc(); /* Standard C library allocation */ + +/* IMPORT INT get_byte() + * + * - This external (machine specific) function is expected to return + * either the next byte from the GIF file, or a negative number, as + * defined in ERRS.H. + */ +IMPORT INT get_byte(); + +/* IMPORT INT out_line(pixels, linelen) + * UBYTE pixels[]; + * INT linelen; + * + * - This function takes a full line of pixels (one byte per pixel) and + * displays them (or does whatever your program wants with them...). It + * should return zero, or negative if an error or some other event occurs + * which would require aborting the decode process... Note that the length + * passed will almost always be equal to the line length passed to the + * decoder function, with the sole exception occurring when an ending code + * occurs in an odd place in the GIF file... In any case, linelen will be + * equal to the number of pixels passed... + */ +IMPORT INT out_line(); + +/* IMPORT INT bad_code_count; + * + * This value is the only other global required by the using program, and + * is incremented each time an out of range code is read by the decoder. + * When this value is non-zero after a decode, your GIF file is probably + * corrupt in some way... + */ +//IMPORT INT bad_code_count; +int bad_code_count; + +#define NULL 0 +#define MAX_CODES 4095 + +/* Static variables */ +LOCAL WORD curr_size; /* The current code size */ +LOCAL WORD clear; /* Value for a clear code */ +LOCAL WORD ending; /* Value for a ending code */ +LOCAL WORD newcodes; /* First available code */ +LOCAL WORD top_slot; /* Highest code for current size */ +LOCAL WORD slot; /* Last read code */ + +/* The following static variables are used + * for seperating out codes + */ +LOCAL WORD navail_bytes = 0; /* # bytes left in block */ +LOCAL WORD nbits_left = 0; /* # bits left in current byte */ +LOCAL UTINY b1; /* Current byte */ +LOCAL UTINY byte_buff[257]; /* Current block */ +LOCAL UTINY *pbytes; /* Pointer to next byte in block */ + +LOCAL LONG code_mask[13] = { + 0, + 0x0001, 0x0003, + 0x0007, 0x000F, + 0x001F, 0x003F, + 0x007F, 0x00FF, + 0x01FF, 0x03FF, + 0x07FF, 0x0FFF + }; + + +/* This function initializes the decoder for reading a new image. + */ +LOCAL WORD init_exp(size) + WORD size; + { + curr_size = size + 1; + top_slot = 1 << curr_size; + clear = 1 << size; + ending = clear + 1; + slot = newcodes = ending + 1; + navail_bytes = nbits_left = 0; + return(0); + } + +/* get_next_code() + * - gets the next code from the GIF file. Returns the code, or else + * a negative number in case of file errors... + */ +LOCAL WORD get_next_code() + { + WORD i, x; + ULONG ret; + + if (nbits_left == 0) + { + if (navail_bytes <= 0) + { + + /* Out of bytes in current block, so read next block + */ + pbytes = byte_buff; + if ((navail_bytes = get_byte()) < 0) + return(navail_bytes); + else if (navail_bytes) + { + for (i = 0; i < navail_bytes; ++i) + { + if ((x = get_byte()) < 0) + return(x); + byte_buff[i] = x; + } + } + } + b1 = *pbytes++; + nbits_left = 8; + --navail_bytes; + } + + ret = b1 >> (8 - nbits_left); + while (curr_size > nbits_left) + { + if (navail_bytes <= 0) + { + + /* Out of bytes in current block, so read next block + */ + pbytes = byte_buff; + if ((navail_bytes = get_byte()) < 0) + return(navail_bytes); + else if (navail_bytes) + { + for (i = 0; i < navail_bytes; ++i) + { + if ((x = get_byte()) < 0) + return(x); + byte_buff[i] = x; + } + } + } + b1 = *pbytes++; + ret |= b1 << nbits_left; + nbits_left += 8; + --navail_bytes; + } + nbits_left -= curr_size; + ret &= code_mask[curr_size]; + return((WORD)(ret)); + } + + +/* The reason we have these seperated like this instead of using + * a structure like the original Wilhite code did, is because this + * stuff generally produces significantly faster code when compiled... + * This code is full of similar speedups... (For a good book on writing + * C for speed or for space optomisation, see Efficient C by Tom Plum, + * published by Plum-Hall Associates...) + */ +LOCAL UTINY stack[MAX_CODES + 1]; /* Stack for storing pixels */ +LOCAL UTINY suffix[MAX_CODES + 1]; /* Suffix table */ +LOCAL UWORD prefix[MAX_CODES + 1]; /* Prefix linked list */ + +/* WORD decoder(linewidth) + * WORD linewidth; * Pixels per line of image * + * + * - This function decodes an LZW image, according to the method used + * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded + * will generate a call to out_line(), which is a user specific function + * to display a line of pixels. The function gets it's codes from + * get_next_code() which is responsible for reading blocks of data and + * seperating them into the proper size codes. Finally, get_byte() is + * the global routine to read the next byte from the GIF file. + * + * It is generally a good idea to have linewidth correspond to the actual + * width of a line (as specified in the Image header) to make your own + * code a bit simpler, but it isn't absolutely necessary. + * + * Returns: 0 if successful, else negative. (See ERRS.H) + * + */ + +WORD decoder(linewidth) + WORD linewidth; + { + FAST UTINY *sp, *bufptr; + UTINY *buf; + FAST WORD code, fc, oc, bufcnt; + WORD c, size, ret; + + /* Initialize for decoding a new image... + */ + if ((size = get_byte()) < 0) + return(size); + if (size < 2 || 9 < size) + return(BAD_CODE_SIZE); + init_exp(size); + + /* Initialize in case they forgot to put in a clear code. + * (This shouldn't happen, but we'll try and decode it anyway...) + */ + oc = fc = 0; + + /* Allocate space for the decode buffer + */ + if ((buf = (UTINY *)malloc(linewidth + 1)) == NULL) + return(OUT_OF_MEMORY); + + /* Set up the stack pointer and decode buffer pointer + */ + sp = stack; + bufptr = buf; + bufcnt = linewidth; + + /* This is the main loop. For each code we get we pass through the + * linked list of prefix codes, pushing the corresponding "character" for + * each code onto the stack. When the list reaches a single "character" + * we push that on the stack too, and then start unstacking each + * character for output in the correct order. Special handling is + * included for the clear code, and the whole thing ends when we get + * an ending code. + */ + while ((c = get_next_code()) != ending) + { + + /* If we had a file error, return without completing the decode + */ + if (c < 0) + { + free(buf); + return(0); + } + + /* If the code is a clear code, reinitialize all necessary items. + */ + if (c == clear) + { + curr_size = size + 1; + slot = newcodes; + top_slot = 1 << curr_size; + + /* Continue reading codes until we get a non-clear code + * (Another unlikely, but possible case...) + */ + while ((c = get_next_code()) == clear) + ; + + /* If we get an ending code immediately after a clear code + * (Yet another unlikely case), then break out of the loop. + */ + if (c == ending) + break; + + /* Finally, if the code is beyond the range of already set codes, + * (This one had better NOT happen... I have no idea what will + * result from this, but I doubt it will look good...) then set it + * to color zero. + */ + if (c >= slot) + c = 0; + + oc = fc = c; + + /* And let us not forget to put the char into the buffer... And + * if, on the off chance, we were exactly one pixel from the end + * of the line, we have to send the buffer to the out_line() + * routine... + */ + *bufptr++ = c; + if (--bufcnt == 0) + { + if ((ret = out_line(buf, linewidth)) < 0) + { + free(buf); + return(ret); + } + bufptr = buf; + bufcnt = linewidth; + } + } + else + { + + /* In this case, it's not a clear code or an ending code, so + * it must be a code code... So we can now decode the code into + * a stack of character codes. (Clear as mud, right?) + */ + code = c; + + /* Here we go again with one of those off chances... If, on the + * off chance, the code we got is beyond the range of those already + * set up (Another thing which had better NOT happen...) we trick + * the decoder into thinking it actually got the last code read. + * (Hmmn... I'm not sure why this works... But it does...) + */ + if (code >= slot) + { + if (code > slot) + ++bad_code_count; + code = oc; + *sp++ = fc; + } + + /* Here we scan back along the linked list of prefixes, pushing + * helpless characters (ie. suffixes) onto the stack as we do so. + */ + while (code >= newcodes) + { + *sp++ = suffix[code]; + code = prefix[code]; + } + + /* Push the last character on the stack, and set up the new + * prefix and suffix, and if the required slot number is greater + * than that allowed by the current bit size, increase the bit + * size. (NOTE - If we are all full, we *don't* save the new + * suffix and prefix... I'm not certain if this is correct... + * it might be more proper to overwrite the last code... + */ + *sp++ = code; + if (slot < top_slot) + { + suffix[slot] = fc = code; + prefix[slot++] = oc; + oc = c; + } + if (slot >= top_slot) + if (curr_size < 12) + { + top_slot <<= 1; + ++curr_size; + } + + /* Now that we've pushed the decoded string (in reverse order) + * onto the stack, lets pop it off and put it into our decode + * buffer... And when the decode buffer is full, write another + * line... + */ + while (sp > stack) + { + *bufptr++ = *(--sp); + if (--bufcnt == 0) + { + if ((ret = out_line(buf, linewidth)) < 0) + { + free(buf); + return(ret); + } + bufptr = buf; + bufcnt = linewidth; + } + } + } + } + ret = 0; + if (bufcnt != linewidth) + ret = out_line(buf, (linewidth - bufcnt)); + free(buf); + return(ret); + } + diff --git a/GIF/Errs.h b/GIF/Errs.h new file mode 100644 index 0000000..54fa92e --- /dev/null +++ b/GIF/Errs.h @@ -0,0 +1,14 @@ +/* Various error codes used by decoder + * and my own routines... It's okay + * for you to define whatever you want, + * as long as it's negative... It will be + * returned intact up the various subroutine + * levels... + */ +#define OUT_OF_MEMORY -10 +#define BAD_CODE_SIZE -20 +#define READ_ERROR -1 +#define WRITE_ERROR -2 +#define OPEN_ERROR -3 +#define CREATE_ERROR -4 + diff --git a/GIF/GIF.H b/GIF/GIF.H new file mode 100644 index 0000000..157b9bd --- /dev/null +++ b/GIF/GIF.H @@ -0,0 +1,16 @@ +#ifndef _GIF__H +#define _GIF__H + +char gif_file [512000]; +char *gif_picture; +char gif_palette [768]; +int x_0, x_1, y_0, y_1, gif_size; +long int gif_pozice=0; +int RaW=0; + +int gif_to_buffer (char *filename); + +#define LENGHTGIF 512000 + +#endif + diff --git a/GIF/GIF2.C b/GIF/GIF2.C new file mode 100644 index 0000000..6ff4c64 --- /dev/null +++ b/GIF/GIF2.C @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include "..\types.h" +#include "decoder.c" +#include "..\bgraph.h" + + +char *gif_buffer,*gif_ptr; +char *decomp_buff,*decomp_ptr; +char *comp_buff,*comp_ptr; + +int g_xsize,g_ysize; +char paleta[768]; + +int get_byte() + { + return(*gif_ptr++); + } + +int curline; +char *obrazovka; + +int out_line(char *data,int linelen) + { + memcpy(obrazovka,data,linelen); + memcpy(decomp_ptr,data,linelen); + decomp_ptr+=linelen; + obrazovka+=640; + if (++curline>=g_ysize) return (curline); + return 0; + } + +void setpalette(char *paleta) + { + int i; + + for (i=0;i<256;i++) + { + outp(0x3c6,0xff); + outp(0x3c8,i); + outp(0x3c9,*paleta++>>2); + outp(0x3c9,*paleta++>>2); + outp(0x3c9,*paleta++>>2); + } + } + + +void load_gif(char *filename) + { + FILE *pic; + long lengif; + + + pic=fopen(filename,"rb"); + if (pic==NULL) return; + fseek(pic,0,SEEK_END); + lengif=ftell(pic); + gif_buffer=(char *)malloc(lengif);gif_ptr=gif_buffer; + fseek(pic,6,SEEK_SET); + fread(&g_xsize,2,1,pic); + fread(&g_ysize,2,1,pic); + decomp_buff=(char *)malloc(g_xsize*g_ysize);decomp_ptr=decomp_buff; + fseek (pic, 0x0d, SEEK_SET); + fread(&paleta,768,1,pic); + setpalette(paleta); + fseek (pic, 0x317, SEEK_SET); + lengif-=0x317; + fread(gif_buffer,lengif,1,pic); + curline=0; + decoder(g_xsize); + fclose(pic); + free(gif_buffer); + } + +#define save_nibble(x) if (nibble_sel) {*(comp_ptr++)|=(x)<<4;nibble_sel=!nibble_sel;} else {*(comp_ptr)=(x);nibble_sel=!nibble_sel;} + +int Hi_coder_1() + { + char palette[8]; + long state[8]; + char nibble_sel=0; + long picsize,cntr=0; + long r_size=0; + + memset(palette,0x0,8); + memset(state,0x0,4*8); + picsize=g_xsize*g_ysize; + + while (picsize) + { + char i,b; + + b=*decomp_ptr++;cntr++; + for (i=0;i<8;i++) if (palette[i]==b) break; + if (i!=8) + { + save_nibble(i); + state[i]=cntr; + r_size++; + } + else + { + long min=0x7fffffff;char sl=0; + + for (i=0;i<8;i++) + if (state[i]> 4); + r_size+=3; + } + picsize--; + } + r_size>>=1; + return r_size; + } + + +void prepare_compress() + { + comp_buff=(char *)malloc(512000); + comp_ptr=comp_buff; + decomp_ptr=decomp_buff; + } + + +int main() + { + initmode256("..\xlat256.pal"); + memset(lbuffer,0xff,640*480); + getchar(); + obrazovka=(char *)lbuffer; + load_gif("desk_d.gif"); + prepare_compress(); + Hi_coder_1(); + getchar(); + return 0; + } + + diff --git a/GIF/GIF2XED.C b/GIF/GIF2XED.C new file mode 100644 index 0000000..e0864ac --- /dev/null +++ b/GIF/GIF2XED.C @@ -0,0 +1,39 @@ +#include +#include +#include "gif.h" + +unsigned short new_palette [256]; + +void main (int argc, char *argv[]) +{ + FILE *xed; + char gif[13]; + int x,y; + + memmove (gif, argv[1], 13); + xed=fopen("new.xed","wb"); + + gif_to_buffer (gif); + + y=0; + for (x=0; x<=767; x+=3) + { + new_palette[y]=gif_palette[(x+2)]; + new_palette[y]|=gif_palette[(x+1)]<<5; //*32; + new_palette[y]|=gif_palette[x]<<10; //*1024; + y++; + } + + fputc (x_0,xed); + fputc (x_1,xed); + fputc (y_0,xed); + fputc (y_1,xed); + fputc (8,xed); + fputc (0,xed); + + fwrite (new_palette, 256, 2, xed); + fwrite (gif_picture, gif_size, 1, xed); + + fclose (xed); +} + diff --git a/GIF/Gif.c b/GIF/Gif.c new file mode 100644 index 0000000..e551905 --- /dev/null +++ b/GIF/Gif.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include "decoder.c" +#include "gif.h" + +int get_byte () +{ + int x; + x=gif_file[gif_pozice]; + gif_pozice++; + if (gif_pozice==LENGHTGIF) return (READ_ERROR); else return (x); +} + +int out_line (char *pixels, int linelen) +{ + memmove ((gif_picture+linelen*RaW), pixels, linelen); + RaW++; + if (RaW<=480) return (RaW); else return (0); +} + +int gif_to_buffer (char *filename) +{ + FILE *picture; + int x; + char mezi[4]; + +//------------------------------------------------------------------------- +// Nacteni GIFu +//------------------------------------------------------------------------- + picture=fopen(filename,"rb"); + +// Read size and alloc memory + fseek (picture, 6, SEEK_SET); + fread (mezi, 4, 1, picture); + gif_size=(mezi[0]+mezi[1]*256)*(mezi[2]+mezi[3]*256); + x_0=mezi[0]; + x_1=mezi[1]; + y_0=mezi[2]; + y_1=mezi[3]; + gif_picture=(char*)malloc( (gif_size*sizeof(gif_picture)) ); + +// Read and prepare palette + fseek (picture, 0x0d, SEEK_SET); + fread (gif_palette, 768, 1, picture); + for (x=0; x<=768; x++) gif_palette[x]>>=3; + +// Read coded picture + fseek (picture, 0x317, SEEK_SET); + fread (gif_file, LENGHTGIF, 1, picture); + +// Decode picture + RaW=0; + decoder (640); + fclose (picture); +//------------------------------------------------------------------------- + +return (0); +} + diff --git a/GIF/STD.H b/GIF/STD.H new file mode 100644 index 0000000..ba7c0d7 --- /dev/null +++ b/GIF/STD.H @@ -0,0 +1,16 @@ +/* STD.H - My own standard header file... + */ + +#define LOCAL static +#define IMPORT extern + +#define FAST register + +typedef short WORD; +typedef unsigned short UWORD; +typedef char TEXT; +typedef unsigned char UTINY; +typedef long LONG; +typedef unsigned long ULONG; +typedef int INT; + diff --git a/INST/SETUP.C b/INST/SETUP.C new file mode 100644 index 0000000..6a305f2 --- /dev/null +++ b/INST/SETUP.C @@ -0,0 +1,1427 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "setup.h" +#include "setvideo.h" +#include "setuplib.h" +#include "setupcpy.h" + +#define TEST_MUSIC "\\SNDTEST.MUS" +#define SETUP_BATCH "SETUP.BAT" +#define _SOURCE_ copy_source_path +#define ER_NAME "c:\\skeldal.!!!" +#define VEL_RAMECEK 8 + +#define VMODE "VMODE" +#define SOUND_DEVICE "SOUND_DEVICE" + +#define SETUP_NAME "SETUP.EXE" + +word *ramecky[VEL_RAMECEK]; + +#define SKELDAL "SKELDAL" +#define SKELDAL_INI SKELDAL".INI" +#define CONCAT(t,s1,s2) strcat(strcpy(t=alloca(strlen(s1)+strlen(s2)+1),s1),s2) +void *bbutt; + +char *copy_source_path; +char *test_sound_name; +char *program_data_path=NULL; +char setup_mode=0; + +char *pgm_name; + +TSTR_LIST setup_ini; + +typedef struct tsound + { + int device,port,irq,dma; + }TSOUND; + + +FILE *ini; +word *vga_font; +word *icones; +word icone_color[7]={0x2108,0x7fff,0x000f,0x4210,0x6f7b}; +//static char target_path[256]="E:\HRY\SKELDAL\"; +char *source_path; +char target_path[2049]; +static TSOUND sound_info={0,0,0,0}; +static int vmode=0; +static char mixer_running=0; +static char back=0; +static char install_type; +static long install_sizes[3]; +static long maxcopy=1; +TSTR_LIST handbook=NULL; +TSTR_LIST dirlist=NULL; +TSTR_LIST disklist=NULL; +int win_handbook=-1; +char rescue_mode=0; +char *inifile=NULL; + +#pragma off (stack_checking) + +static char home_path(char *source_path) + { + unsigned x,z; + _dos_setdrive(source_path[0]-'@',&x); + _dos_getdrive(&z); + if (z!=source_path[0]-'@') return 1; + chdir("\\"); + chdir(source_path); + return 0; + } +char error_device(word a,char b,char c) + { + a,b,c; + + errno=-1; + return _ERR_FAIL; + } + +int create_er_file() + { + FILE *f; + if (!access(ER_NAME,F_OK)) return 0; + + f=fopen(ER_NAME,"w"); + fprintf(f,"7925536\n"); + fprintf(f,"Toto je zachranny soubor pro instalacni program ke hre BRANY SKELDALU. Pokud se posledni instalace nezdarila, nemazte tento soubor!"); + fclose(f); + return 1; + } + +void remove_er_file() + { + FILE *f; + + f=fopen(ER_NAME,"r"); + if (f!=NULL) + { + long l=0; + fscanf(f,"%d",&l); + fclose(f); + if (l==7925536) remove(ER_NAME); + } + } + + +static conv_ramecek(word *ram) + { + int i; + word xs,ys; + char *ptr; + word *targ; + + xs=ram[0]; + ys=ram[1]/VEL_RAMECEK; + ptr=(char *)(ram+3+256); + for(i=0;i"); + } + for(i=0;i"); + set_value(0,20,""); + } + else + { + sprintf(s,"VESA %d.%02d",si.version/256,si.version%256); + set_value(0,10,s); + set_value(0,20,si.oemstr); + } + set_value(0,30,gr_mody[vmode]);do_events(); + sound_detect(&sound_info.device,&sound_info.port,&sound_info.dma,&sound_info.irq); + set_value(0,40,device_name(sound_info.device)); + if (sound_info.device==DEV_WSS || sound_info.device==DEV_ULTRA) + sprintf(s,"Port %X Dma %X",sound_info.port,sound_info.dma); + else sprintf(s,"Port %X Dma %X Irq %X",sound_info.port,sound_info.dma,sound_info.irq); + set_value(0,50,s); + set_value(0,60,get_cdrom()); + set_enable(0,6,1); + set_enable(0,5,1); + } + +static EVENT_PROC(esc_mode2) + { + GET_USER_PTR(); + WHEN_MSG(E_KEYBOARD) + { + if (GET_DATA(char)==27) + { + donegr(); + if (vmode==0)initgr_low();else initgr_spec(vmode); + zobraz_mysku(); + redraw_desktop(); + goto_control(0); + terminate(); + } + } + } + +static char test_mode() + { + char i,j,c; + + if (msg_box("Test grafiky",'\x1', + "Instal tor nynˇ vyzkou¨ˇ zvolen grafick re‘im. " + "Pokud obrazovka z–stane ‡ern , nebo zobrazˇ nesmysly, stisknte " + "ESC a instal tor obnovˇ p–vodnˇ re‘im.","Start","Zru¨it",NULL)==2) return 0; + send_message(E_ADD,E_KEYBOARD,esc_mode2); + donegr(); + i=initgr_spec(f_get_value(0,9)); + if (!i) + { + zobraz_mysku(); + redraw_desktop(); + } + if (!i && (j=msg_box("Test grafiky",'\x2',"Vidi¨ prost©edˇ instal toru spr vn?","Ano","Ne",NULL))==1) + { + vmode=f_get_value(0,9); + if (vmode==0) initgr_low(); + zobraz_mysku(); + c=1; + } + else + { + c_set_value(0,9,vmode); + if (j!=0) + { + donegr(); + if (vmode==0) initgr_low();else initgr_spec(vmode); + zobraz_mysku(); + redraw_desktop(); + } + c=0; + } + send_message(E_DONE,E_KEYBOARD,esc_mode2); + return c; + } + +static TSTR_LIST video_ls=NULL; + +static void create_video_ls() + { + int i; + if (video_ls==NULL) + { + video_ls=create_list(3); + for(i=0;i<3;i++) str_add(&video_ls,gr_mody[i]); + } + } + +static void select_vga() + { + default_font=&font6x9; + def_dialoge(20,300,156,156,"Kvalita grafiky",2); + define(9,0,20,156,80,0,listbox,video_ls,0x03ff,0);c_default(vmode); + property(NULL,vga_font,NULL,WINCOLOR); + define(20,38,5,80,20,3,button,"Zmnit te");on_change(test_mode); + property(bbutt,NULL,NULL,BUTTONCOLOR); + redraw_window(); + } + + +static void change_dma() + { + int i,j; + + i=f_get_value(0,30); + j=f_get_value(0,35)+3; + if (o_aktual->id==30) + { + c_set_value(0,30,i); + c_set_value(0,35,i-3); + } + else + { + c_set_value(0,30,j); + c_set_value(0,35,j-3); + } + } + +static void select_mode_win() + { + def_dialoge(224,270,192,156,"Instalovat",2); + default_font=&font6x9; + define(10,30,40,132,30,0,button,"Automaticky");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(terminate); + define(30,30,80,132,30,0,button,"Podle p© nˇ");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(terminate); + define(40,50,15,92,20,3,button,"Konec");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(stop_copy); + redraw_window(); + } + +static void select_mode_win_setup() + { + def_dialoge(224,270,192,156,"Mo‘nosti:",2); + default_font=&font6x9; + define(10,30,40,132,30,0,button,"Nastavenˇ");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(terminate); + define(30,30,80,132,30,0,button,"Odinstalov nˇ");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(terminate); + define(40,50,15,92,20,3,button,"Konec");property(bbutt,NULL,NULL,BUTTONCOLOR);on_change(stop_setup); + redraw_window(); + } + + + +static void device_select() + { + int i,p; + i=f_get_value(0,9); + set_enable(0,40,i!=DEV_ULTRA && i!=DEV_WSS && i!=DEV_NOSOUND && i!=DEV_DAC); + p=i==DEV_SB16 || i==DEV_ULTRA; + set_enable(0,35,p); + if (p==0) + { + c_set_value(0,30,1); + c_set_value(0,35,1-3); + } + set_enable(0,20,i!=DEV_NOSOUND); + set_enable(0,30,i!=DEV_NOSOUND && i!=DEV_DAC); + set_enable(0,50,i!=DEV_NOSOUND); + } + +static void device_select2() + { + int i; + + device_select(); + i=f_get_value(0,9); + if (i==DEV_DAC) + { + char c; + def_dialoge(270,240,100,100,device_name(i),3); + define(10,10,25,60,40,0,radio_butts,3,"LPT 1","LPT 2","PC Speaker");c_default(0); + define(20,10,5,80,20,2,button,"Ok");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(terminate); + redraw_window(); + escape(); + c=f_get_value(0,10); + close_current(); + if (c==0) set_value(0,20,"378");else + if (c==1)set_value(0,20,"278"); + else set_value(0,20,"042"); + } + if (i==DEV_SB16 || i==DEV_ULTRA || i==DEV_SBPRO || i==DEV_SB20 || i==DEV_SB10) + set_value(0,20,"220"); + if (i==DEV_WSS) set_value(0,20,"530"); + } + +static void select_sound(); +static void detect_sound() + { + if (msg_box("Rozpozn nˇ zvukov‚ karty",'\x2',"Opravdu chce¨ nechat rozpoznat zvukovou kartu? Na nkterch po‡ˇta‡ˇch m–‘e automatick‚ rozpozn v nˇ zp–sobit zatuhnutˇ po‡ˇta‡e.","Ano","Ne",NULL)==2) return; + if (mixer_running) stop_mixing(); + mixer_running=0; + set_enable(0,70,mixer_running); + sound_detect(&sound_info.device,&sound_info.port,&sound_info.dma,&sound_info.irq); + close_current(); + select_sound(); + } + +static int sound_win=-1; + +static char sound_scan() + { + char buffer[20]; + char dmas[]={0,1,3,5,6,7}; + char irqs[]={2,3,5,7}; + + sound_info.device=f_get_value(sound_win,9); + if (sound_info.device!=DEV_NOSOUND) + { + if (sound_info.device==DEV_DAC) + if (msg_box("Varov nˇ!",'\x1',"Vybran‚ zvukov‚ za©ˇzenˇ pou‘ˇv  nestandardnˇ p©ˇstupy a vyu‘ˇv  " + "nkterch skrytch trik– syst‚mu. Na nkterch po‡ˇta‡ˇch nemusˇ pracovat spr vn. " + "Toto za©ˇzenˇ nedok ‘e pracovat pod WINDOWS95 nebo jinm OS vjma DOSu. " + "Pro zrychlenˇ pr ce odinstalujte ze syst‚mu jakkoliv EMM manager (EMM386, QEMM, apod.) " + "Chcete pokra‡ovat?","Ano","Ne",NULL)==2) return 1; + get_value(sound_win,20,buffer); + if (sscanf(buffer,"%x",&sound_info.port)!=1) + { + msg_box("Pozor!",'\x1',"Musˇ¨ vyplnit spr vn Port","Ok",NULL); + return 1; + } + } + sound_info.dma=dmas[f_get_value(sound_win,30)]; + sound_info.irq=irqs[f_get_value(sound_win,40)]; + return 0; + } + + +static void test_sound() + { + if (mixer_running) stop_mixing(); + if (sound_scan()) return; + set_mixing_device(sound_info.device,22050,sound_info.port,sound_info.dma,sound_info.irq); + start_mixing(); + change_music(test_sound_name); + mix_back_sound(2); + mix_back_sound(0); + mixer_running=1; + set_enable(0,70,mixer_running); + } + +static void stop_sound() + { + if (mixer_running) + { + stop_mixing(); + mixer_running=0; + set_enable(sound_win,70,mixer_running); + } + } + +void select_sound() + { + TSTR_LIST ls; + int i; + char buff[30]; + + ls=create_list(8); + default_font=&font6x9; + for(i=0;i<8;i++) str_add(&ls,device_name(i)); + str_replace(&ls,0,""); + sound_win=def_dialoge(200,300,300,156,"Zvukov  karta",2); + define(9,2,20,170,85,0,listbox,ls,0x03ff,0);c_default(sound_info.device);on_change(device_select2); + property(def_border(0,0x4210),vga_font,NULL,WINCOLOR); + define(-1,180,20,1,1,0,label,"Port:"); + define(20,10,20,30,12,1,input_line,3);property(def_border(0,0x4210),vga_font,NULL,WINCOLOR); + set_default(itoa(sound_info.port,buff,16)); + define(-1,180,40,1,1,0,label,"DMA:"); + i=sound_info.dma;i-=(i>2)+(i>4); + define(30,40,40,30,30,1,radio_butts,3,"0","1","3");c_default(i);on_change(change_dma); + define(35,10,40,30,30,1,radio_butts,3,"5","6","7");c_default(i-3);on_change(change_dma); + define(-1,180,80,1,1,0,label,"IRQ:"); + i=sound_info.irq;i-=2*(i>1)+(i>4)+(i>6); + define(40,40,80,30,40,1,radio_butts,4,"2","3","5","7");c_default(i); + define(50,10,5,80,20,2,button,"Test");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(test_sound); + define(60,100,5,80,20,2,button,"Rozpoznat");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(detect_sound); + define(70,190,5,80,20,2,button,"Stop");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(stop_sound); + redraw_window(); + set_enable(0,70,mixer_running); + device_select(); + } + +static void back_start() + { + back=1; + stop_sound(); + sound_scan(); + while (waktual!=NULL) close_current(); + terminate(); + } + +static void control_window(void *forward,void *back,void *help); +static void control_next1(); + +static void control_back1() + { + close_current(); + get_value(0,60,target_path); + while (waktual!=NULL) close_current(); + exit_wait=0; + select_vga(); + select_sound(); + control_window(control_next1,back_start,open_help); + } + +static trace_chdir(char *what) + { + char *c; + char *d; + + c=alloca(strlen(what)+1); + strcpy(c,what); + d=strrchr(c,'\\'); + while (d!=NULL) + { + if (chdir(c)==0) + { + home_path(c); + return; + } + *d=0; + d=strrchr(c,'\\'); + } + strcat(c,"\\"); + home_path(c); + } + + +void static show_space(char device) + { + char buff[100]; + static long lastvalue; + static char lastdevice; + + device=toupper(device); + if (device>='A' && device<='Z') + { + if (device!=lastdevice) lastvalue=get_disk_free(device-'@')/1024; + sprintf(buff,"Na disku %c: je volnch %d Kb",device,lastvalue); + lastdevice=device; + set_value(0,80,buff); + } + } + +static open_load_window() + { + char c; + get_value(0,60,target_path); + trace_chdir(target_path); + getcwd(target_path,2047); + load_window(); + escape(); + home_path(source_path); + c=o_aktual->id==150; + if (c) + { + get_value(0,10,target_path); + } + close_current(); + if (c) + set_value(0,60,target_path); + else + get_value(0,60,target_path); + show_space(target_path[0]); + } + +static char create_ini(char *path,char *name) + { + + if (inifile!=NULL) + { + fclose(ini); + remove(inifile); + free(inifile); + } + inifile=NewArr(char,strlen(path)+strlen(name)+2); + sprintf(inifile,"%s\\%s",path,name); + ini=fopen(inifile,"w"); + if (ini==NULL) return 1; + add_to_list(inifile); + fprintf(ini,"vmode %d\n", vmode); + fprintf(ini,"sound_device %d %x %d %d\n",sound_info.device,sound_info.port,sound_info.dma,sound_info.irq); + fprintf(ini,"sound_mixfreq 22049\n"); + fprintf(ini,"default_map lespred.map\n"); + fprintf(ini,"preload 1\n"); + fprintf(ini,"game_speed 5\n"); + return 0; + } + /* +static char create_setup_batch(char *path,char *name) + { + char *st; + FILE *batch; + + st=alloca(strlen(path)+strlen(name)+2); + sprintf(st,"%s\\%s",path,name); + batch=fopen(st,"w"); + if (batch==NULL) return 1; + fputs( + "@Echo off\n" + ":skok\n" + "Echo Vloz CD \"Brany Skeldalu\" do mechaniky\n" + "Echo a stiskni jakoukoliv klavesu. \n" + "Echo.\n" + "Echo Kombinace CNTR+C prerusi program....\n" + "Pause > NUL\n",batch); + fprintf(batch,"if not exist %s goto skok\n",pgm_name); + fprintf(batch,"%s -s \n",pgm_name); + fclose(batch); + return 0; + } + */ +static void close_ini() + { + if (ini!=NULL) fclose(ini); + } + +static void copy_self(char alloc) + { + static char *t; + + if (alloc) + { + t=NewArr(char,strlen(target_path)+strlen(SETUP_NAME)+2); + sprintf(t,"%s\\%s",target_path,SETUP_NAME); + cpy_file(pgm_name,t); + } + else free(t); + } + +static long self_size() + { + struct find_t f; + + _dos_findfirst(pgm_name,_A_NORMAL,&f); + return f.size; + } + +static void start_install() + { + long diskfree; + char error=0,autostart; + get_value(0,60,target_path); + if (find_object(waktual,70)!=NULL) autostart=f_get_value(0,70); else autostart=1; + strupr(target_path); + if (validate_path(target_path)==0) + { + msg_box("Cesta je ¨patn",'\x1',"Cesta s cˇlovm adres ©em je chybn zad na. Nepou‘ˇvejte dlouh‚ n zvy z WINDOWS 95!","OK",NULL); + return; + } + get_script(_SOURCE_,target_path); + switch (o_aktual->id) + { + case 10:install_type=INST_MIN;break; + case 20:install_type=INST_MED;break; + case 30:install_type=INST_MAX;break; + } + maxcopy=install_sizes[install_type]; + diskfree=get_disk_free(target_path[0]-'@'); + if (maxcopy>diskfree) + { + if (msg_box("Nedostatek mˇsta!",'\x1',"Instal tor vypo‡ˇtal, ‘e BS zaberou vˇce mˇsta ne‘ m te na sv‚m disku. " + "Pokud v¨ak pou‘ˇvate komprima‡nˇ program jako je t©eba DRVSPACE, pak mohou bt Łdaje o " + "voln‚m mˇstu nep©esne. I p©es to, ‘e nenˇ voln‚ mˇsto chcete pokra‡ovat?","Ano","Ne",NULL)==2) return; + } + else if (maxcopy+1024*1024>diskfree) + { + if (msg_box("M lo mˇsta",'\x2',"Po nainstalov nˇ by mlo zbt alespo¤ 1MB pro bh. Sou‡asn prostor" + "umo‘¤uje hru nainstalovat, av¨ak hru nebude mo‘n‚ spustit. Pokra‡ovat?","Ano","Ne",NULL)==2) return; + } + maxcopy=maxcopy<<1; + while (waktual!=NULL) close_current(); + cascade_mkdir(target_path); + if (create_ini(target_path,SKELDAL_INI)) + { + msg_box(PRG_HEADER,'\x1',"Nemohu vytvo©it konfigura‡nˇ soubor. Zkontroluj spravnost z pisu cesty","Ok",NULL); + clean_up(); + return; + } +// create_setup_batch(target_path,SETUP_BATCH); + display_progress(); + stop_sound(); + switch (install_type) + { + case INST_MIN:if (do_script(0) || do_script(-1) || do_script(-2) || do_script(-3)) error=1;break; + case INST_MED:if (do_script(0) || do_script(1) || do_script(-2) || do_script(-3)) error=1;break; + case INST_MAX:if (do_script(0) || do_script(1) || do_script(2) || do_script(3)) error=1; + break; + } + copy_self(1); + cpy_flush(); + copy_self(0); + close_ini(); + if (error) shutdown(),exit(1); + close_current(); + do_events(); + if (!autostart) msg_box("Hotovo",' ',"Hra 'Br ny Skeldalu' je Łsp¨n nainstalov na. Spu¨tnˇ provete z p©ˇkazov‚ © dky naps nˇm 'SKELDAL'","Konec",NULL); + purge_file_list(); + shutdown(); + home_path(target_path); + if (autostart) + { + puts("Chvilicku strpeni..."); + exit(254); + } + else exit(0); + } + +static EVENT_PROC (show_space_event) + { + OBJREC *o; + + o=(OBJREC *)user_ptr; + if (msg->msg==E_KEYBOARD || msg->msg==E_CURSOR_TICK) + { + char *c; + + c=o->data; + if (c[1]==':') + show_space(c[0]); + if (msg->msg==E_KEYBOARD) + *(char *)msg->data=toupper(*(char *)msg->data); + } + } + +static show_space_exit() + { + EVENT_MSG msg; + + msg.msg=E_KEYBOARD; + show_space_event(&msg,(void **)o_aktual); + } + + + +static void rozsah_window() + { + char buff[100]; + char *text="Velikost na HD zhruba %d KB"; + + exit_wait=0; + default_font=&font6x9; + def_dialoge(146,160,348,264,"Rozsah instalace",2); + define(10,10,30,70,30,0,button,"Minim lnˇ");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(start_install); + define(-1,90,30,1,1,0,label,"Instaluje jen nejd–le‘itj¨ˇ soubory na HD"); + define(-1,90,40,1,1,0,label,"V¨e ostatnˇ se pak na‡ˇt  p©ˇmo z CD"); + sprintf(buff,text,install_sizes[0]/1024); + define(-1,90,50,1,1,0,label,buff); + define(20,10,80,70,30,0,button,"St©ednˇ");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(start_install); + define(-1,90,80,1,1,0,label,"Instaluje v¨echny datov‚ soubory na HD"); + define(-1,90,90,1,1,0,label,"Hudba a video se ‡tou p©ˇmo z CD"); + sprintf(buff,text,install_sizes[1]/1024); + define(-1,90,100,1,1,0,label,buff); + define(30,10,130,70,30,0,button,"Maxim lnˇ");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(start_install); + define(-1,90,130,1,1,0,label,"Instaluje v¨e na v ¨ HD v‡etn hudby"); + define(-1,90,140,1,1,0,label,"a videa. Z CD se nena‡ˇt  v–bec nic."); + sprintf(buff,text,install_sizes[2]/1024); + define(-1,90,150,1,1,0,label,buff); + define(40,10,180,70,20,0,button,"Slo‘ka");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(open_load_window); + define(60,90,185,250,11,0,input_line,2048);property(def_border(1,0x4210),&font6x9,NULL,0x7fff); + set_default(target_path); + on_event(show_space_event);on_exit(show_space_exit); + define(70,40,220,200,10,0,check_box,"Po nainstalov nˇ hru automaticky spustit.");c_default(1); + define(80,10,10,250,11,2,view_line,100);set_default(""); + show_space(target_path[0]); + } + +static void automatic_window() + { + char buff[100]; + char *text="Hra zabere zhruba %d KB mˇsta"; + + exit_wait=0; + default_font=&font6x9; + def_dialoge(110,200,420,80,"Instalovat kam?",2); + define(40,10,33,70,15,0,button,"Najˇt");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(open_load_window); + define(60,90,35,310,11,0,input_line,2048);property(def_border(1,0x4210),&font6x9,NULL,0x7fff); + set_default(target_path); + on_event(show_space_event);on_exit(show_space_exit); + define(10,10,10,70,20,2,button,"Start");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(start_install); + define(20,90,10,70,20,2,button,"<< Zpt");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(back_start); + sprintf(buff,text,install_sizes[0]/1024); + define(90,180,20,200,10,2,view_line,100);set_default(buff); + define(80,180,10,200,10,2,view_line,100);set_default(""); + show_space(target_path[0]); + redraw_window(); + } + + + +static void control_next1() + { + sound_scan(); + while (waktual!=NULL) close_current(); + rozsah_window(); + control_window(NULL,control_back1,open_help); + } + +static void control_window(void *forward,void *back,void *help) + { + def_dialoge(524,300,96,156,"Mo‘nosti",2); + define(10,8,30,80,20,0,button,"Dal¨ˇ >>");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(forward); + define(20,8,60,80,20,0,button,"<< Zpt");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(back); + define(30,8,90,80,20,0,button,"? Pomoc");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(help); + define(40,8,10,80,20,3,button,"Konec");property(bbutt,&font6x9,NULL,BUTTONCOLOR); + if (setup_mode) on_change(stop_setup);else on_change(stop_copy); + set_enable(0,10,forward!=NULL); + set_enable(0,20,back!=NULL); + set_enable(0,30,help!=NULL); + redraw_window(); + } + +static void run_setup() + { + int id; + + while (waktual!=NULL) close_current(); + get_script(_SOURCE_,""); + { + int minus[3]; + minus[1]=check_size(-2)+check_size(-3); + minus[0]=minus[1]+check_size(-1); + install_sizes[0]=check_size(0)+self_size(); + install_sizes[1]=install_sizes[0]+check_size(1); + install_sizes[2]=install_sizes[1]+check_size(2)+check_size(3); + install_sizes[0]+=minus[0]; + install_sizes[1]+=minus[1]; + id; + } + if (all_finder()) + { + char *c; + getcwd(&target_path,2047); + c=strchr(target_path,0); + c--; + if (*c=='\\') *c=0; + strcat(target_path,"\\"SKELDAL); + } + else + { + target_path[0]=select_disk()+'@'; + target_path[1]=':'; + target_path[2]='\\'; + strcpy(target_path+3,SKELDAL); + } + do + { + home_path(source_path); + back=0; + select_mode_win(); + about_window(); + id=o_aktual->id; + close_current(); + close_current(); + exit_wait=0; + if (id==10) + { + autodetect(); + automatic_window(); + } + if (id==30) + { + if (msg_box("Autodetekce?",'\x1',"Chcete nejprve provest autodetekci hardware?","Ano","Ne",NULL)==1) autodetect(); + select_vga(); + select_sound(); + control_window(control_next1,back_start,open_help); + } + if (id!=40) escape(); + } + while (back); + } + +static void save_ini() + { + char c[50]; + char d; + char err=1; + + if (sound_scan()) return; + d=msg_box("Potvrzenˇ?",'\x2',"Chce¨ zapsat zmny do konfigura‡nˇho souboru hry?","Ano","Ne","Zru¨it",NULL); + if (d==3) return; + if (d==1) + { + sprintf(c,"%d %x %d %d",sound_info.device, + sound_info.port, + sound_info.dma, + sound_info.irq); + add_field_txt(&setup_ini,SOUND_DEVICE,c); + add_field_num(&setup_ini,VMODE,vmode); + home_path(target_path); + err=save_config(setup_ini,SKELDAL_INI); + } + shutdown(); + home_path(target_path); + switch (err) + { + case -1:puts("Pri ukladani se objevila neocekavana chyba. Soubor "SKELDAL_INI" nebyl ulozen");break; + case 0:puts("Nastaveni bylo ulozeno..."); break; + case 1:puts("Nastaveni nebylo zmeneno..."); break; + } + exit(0); + } + +static void deinstall() + { + char ig; + int x,y; + def_dialoge(200,200,250,156,"Odinstalovat?",2); + define(-1,10,30,200,100,0,label,"Tato volba odstranˇ hru z va¨eho disku."); + define(-1,10,40,200,100,0,label,"Pot‚ ji‘ nebude mo‘ne hru spustit"); + define(-1,10,50,200,100,0,label,"do nov‚ho nainstalov nˇ z CD."); + define(10,30,80,150,10,0,check_box,"Zachovat ulo‘en‚ pozice");c_default(1); + define(20,10,10,80,30,3,button,"Ano");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(terminate); + define(30,10,10,80,30,2,button,"Proboha NE");property(bbutt,&font6x9,NULL,BUTTONCOLOR);on_change(terminate); + redraw_window(); + escape(); + if (o_aktual->id==30) + { + close_current(); + return; + } + ig=f_get_value(0,10); + set_enable(0,30,0); + set_enable(0,20,0); + set_enable(0,10,0); + do_events(); + home_path(target_path); + cascade_delete(ig); + chdir(".."); + rmdir(target_path); + home_path(source_path); + curcolor=0; + for(x=319;x>-1;x-=2) + { + y=x*240/320;bar(x,y,639-x,479-y);showview(0,0,0,0); + } + shutdown(); + exit(0); + } + +static void run_resetup() + { + int id; + + while (waktual!=NULL) close_current(); + do + { + home_path(source_path); + back=0; + select_mode_win_setup(); + about_window(); + id=o_aktual->id; + close_current(); + close_current(); + exit_wait=0; + if (id==30) + { + deinstall(); + back=1; + } + if (id==10) + { + select_vga(); + select_sound(); + control_window(save_ini,back_start,NULL); + } + if (id!=40) escape(); + } + while (back); + } + + +#define REPEAT(i,cnt) for(i=0;i=2 && argv[1][0]=='-' && toupper(argv[1][1])=='S') || access(SKELDAL_INI,F_OK)==0) + { + char *c; + char *d; + setup_mode=1; + getcwd(target_path,PATH_MAX+1); + setup_ini=read_config(SKELDAL_INI); + if (setup_ini==NULL) + { + printf("The file %s has not been found. You must reinstall the game\n" + "Insert the CD into driver and run INSTALL.EXE\n",SKELDAL_INI); + printf("Nemohu najit soubor %s. Budes muset hru znovu nainstalovat\n" + "Z CD \"Brany Skeldalu\" spust program INSTALL.EXE\n",SKELDAL_INI); + exit(0); + } + get_num_field(setup_ini,VMODE,&vmode); + c=get_text_field(setup_ini,"CESTA_CD"); + program_data_path=NewArr(char,strlen(c)+1);strcpy(program_data_path,c); + c=strchr(program_data_path,0); + if (c>program_data_path && c[-1]=='\n') c[-1]=0,c--; + if (c>program_data_path && c[-1]=='\\') c[-1]=0; + c=get_text_field(setup_ini,SOUND_DEVICE); + sscanf(c,"%d %x %d %d",&sound_info.device, + &sound_info.port, + &sound_info.dma, + &sound_info.irq); + c=alloca(strlen(argv[0])+1); + strcpy(c,argv[0]); + d=strrchr(c,'\\'); + if (d!=NULL) + { + d[d-c<=2]=0; + home_path(c); + } + } + } + +main(int argc,char **argv) + { + char s; + char *c; + + pgm_name=argv[0]; + check_setup_mode(argc,argv); + if (argc==2 && !setup_mode) copy_source_path=argv[1];else copy_source_path=NULL; + if (!setup_mode) + { + _setvideomode(_TEXTC80); + rescue_mode=!(s=create_er_file()); + if (s && !setup_mode) warning(),getche(); + } + else + s=0; + init_setup(s); + create_video_ls(); + set_mixing_device(0,22050,0,0,0); + c=test_sound_name=NewArr(char, strlen(program_data_path)+strlen(TEST_MUSIC)+1); + sprintf(c,"%s%s",program_data_path,TEST_MUSIC); + if (access(c,F_OK)!=0) + { + shutdown(); + printf("Vloz CD \"Brany Skeldalu\" do jednotky CD-ROM a spust znova instalaci\n" + "Insert CD \"The Gates of the Skeldal\" into CD-ROM and try to run INSTALL again.\n"); + abort(); + } + konec_skladby=skladba_konec; + change_music(c); + mix_back_sound(2); + if (setup_mode) run_resetup(); + else + { + if (!rescue_mode) run_setup(); + if (rescue_mode) + { + ask_video(); + escape(); + } + } + shutdown(); + } diff --git a/INST/SETUP.H b/INST/SETUP.H new file mode 100644 index 0000000..14263b1 --- /dev/null +++ b/INST/SETUP.H @@ -0,0 +1,18 @@ +extern word ikones; +extern word boldcz; +extern word sipka; +extern word font6x9; +extern void *bbutt; +extern word *vga_font; +extern word *icones; +extern word icone_color[]; +extern word ramecek; +extern word *ramecky[]; + +//#define WINCOLOR 0x6318 +#define WINCOLOR (31*1024+31*32+26) +#define LABELCOLOR (11*1024+11*32+06) +#define BUTTONCOLOR (28*1024+24*32+3) +#define PRG_HEADER "Br ny Skeldalu Setup v1."VERSION + +extern FILE *ini; diff --git a/INST/SETUPCPY.C b/INST/SETUPCPY.C new file mode 100644 index 0000000..eebedaf --- /dev/null +++ b/INST/SETUPCPY.C @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include "setupcpy.h" + +#define DATASIZE 32768 +#define INFOBLOCK 1 +#define DATABLOCK 2 +#define ERRORBLOCK 3 + +typedef struct tdatablock + { + void *next; + char block_type; + unsigned short load_size; + char data[DATASIZE]; + }TDATABLOCK; + +typedef struct tinfoblock + { + void *next; + char block_type; + char pathname[2]; + }TINFOBLOCK; + +static void *start=NULL; +static void *end=NULL; +static FILE *cpyout=NULL; +static long progress=0; + +void (*cpy_error)(int,char *); +void (*mem_error_next)(long); + +void (*cpy_progress)(long); + + +static void *alloc_file(char *target_name) + { + TINFOBLOCK *p; + + p=(TINFOBLOCK *)getmem(sizeof(TINFOBLOCK)+strlen(target_name)); + strcpy(p->pathname,target_name); + p->next=NULL; + p->block_type=INFOBLOCK; + return p; + } + +static void *alloc_data() + { + TDATABLOCK *p; + + p=New(TDATABLOCK); + p->next=NULL; + p->load_size=0; + p->block_type=DATABLOCK; + return p; + } + + +static void *load_data(FILE *f) + { + TDATABLOCK *p; + int rc; + int retry=0; + void *end_line; + + p=end_line=alloc_data(); + again: + errno=0; + rc=fread(p->data,1,sizeof(p->data),f); + p->load_size=rc; + if (ferror(f) || rc!=sizeof(p->data) && errno!=0) + { + if (retry) retry--; + else cpy_error(CPERR_READ,NULL); + fseek(f,-rc,SEEK_CUR); + errno=0; + goto again; + } + progress+=p->load_size; + cpy_progress(progress); + return end_line; + } + +static error_mem(long size) + { + TDATABLOCK *p; + TINFOBLOCK *q; + int rc; + + size; + if (start==NULL) mem_error_next(size); + while (start!=NULL) + { + p=start; + q=start; + if (q->block_type==INFOBLOCK) + { + if (cpyout!=NULL) fclose(cpyout); + again: + cpyout=fopen(q->pathname,"wb"); + if (cpyout==NULL) + { + cpy_error(CPERR_OPEN,q->pathname); + goto again; + } + start=q->next; + free(q); + } + else if (p->block_type==DATABLOCK) + { + again2: + rc=fwrite(p->data,1,p->load_size,cpyout); + if (rc!=p->load_size) + { + cpy_error(CPERR_WRITE,q->pathname); + fseek(cpyout,-rc,SEEK_CUR); + goto again2; + } + progress+=p->load_size; + cpy_progress(progress); + start=p->next; + free(p); + } + } + end=NULL; + } + +void cpy_file(char *source,char *target) + { + FILE *f; + TDATABLOCK *p; + TINFOBLOCK *q; + + again: + errno=0; + f=fopen(source,"rb"); + if (f==NULL) + { + cpy_error(CPERR_OPEN,source); + goto again; + } + q=alloc_file(target); + if (start==NULL) start=end=q;else end=(((TDATABLOCK *)end)->next=q); + while (!feof(f)) + { + p=load_data(f); + if (start==NULL) start=end=p;else end=(((TDATABLOCK *)end)->next=p); + } + fclose(f); + } + +void cpy_flush() + { + if (start!=NULL)error_mem(0); + if (cpyout!=NULL)fclose(cpyout); + cpyout=NULL; + } + +void install_cpy() + { + mem_error_next=mem_error; + mem_error=error_mem; + } diff --git a/INST/SETUPCPY.H b/INST/SETUPCPY.H new file mode 100644 index 0000000..e46a382 --- /dev/null +++ b/INST/SETUPCPY.H @@ -0,0 +1,9 @@ +#define CPERR_OPEN 1 +#define CPERR_WRITE 2 +#define CPERR_READ 3 + +extern void (*cpy_error)(int,char *); +extern void (*cpy_progress)(long); +void cpy_file(char *source,char *target); +void cpy_flush(); +void install_cpy(); diff --git a/INST/SETUPLIB.C b/INST/SETUPLIB.C new file mode 100644 index 0000000..936cc70 --- /dev/null +++ b/INST/SETUPLIB.C @@ -0,0 +1,505 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "setuplib.h" +#include "setupcpy.h" +#include "setup.h" + +#define COPY "COPY" +#define MKDIR "MKDIR" +#define INI "INI" + +#define DIR_NAMES 6 +char *dirnames[]= + { + "GAMES.*", + "GAME*.*", + "HRY.*", + "ZABAVA.*", + "SKELDAL", + "NAPOLEON", + }; + +TSTR_LIST file_list=NULL; + +static void done_bar_init(OBJREC *o,long *params) + { + o->userptr=New(long); + *(long *)o->userptr=*params; + } + +static void done_bar_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + long value,max,x3; + + value=*(long *)o->data; + max=*(long *)o->userptr; + x3=x1+(x2-x1)*value/max; + if (x3<=x1) x3=x1; + if (x3>=x2) x3=x2; + bar(x3,y1,x2,y2); + curcolor=o->f_color[1]; + bar(x1,y1,x3,y2); + } + +void done_bar(OBJREC *o) //define(...done_bar,max); + { + o->runs[0]=done_bar_init; + o->runs[1]=done_bar_draw; + o->datasize=4; + } + + + +char select_disk() + { + char last=3; + struct diskfree_t ds; + int max=0,i; + long now; + + for(i=('C'-'@');i<('Z'-'@');i++) + { + if (_dos_getdiskfree(i,&ds)==0) + { + now=ds.avail_clusters*ds.sectors_per_cluster*ds.bytes_per_sector; + if (now>max) + { + max=now; + last=i; + } + } + } + return last; + } + +char dir_finder() + { + struct find_t ft; + int i; + int rc; + + for(i=0;imax && sz[j]datasize=(*len)+1; + } + +static void view_line_draw(int x1,int y1, int x2, int y2, OBJREC *o) + { + char *c; + + bar(x1,y1,x2,y2); + c=(char *)o->data; + if (!*c) return; + set_aligned_position(x2,y1,2,0,c); + outtext(c); + } + + +void view_line(OBJREC *o) + { + o->runs[0]=view_line_init; + o->runs[1]=view_line_draw; + } + + +char get_max_res() + { + if (vesasupport(0x110)) return 2; + if (vesasupport(0x100)) return 1; + return 0; + } + +void add_to_list(char *name) + { + if (file_list==NULL) file_list=create_list(256); + str_add(&file_list,name); + } + +static void copy_1_file(char *init_mask,char *filename,char *target) + { + char *c,*d; + + c=alloca(strlen(init_mask)+strlen(filename)+1); + strcpy(c,init_mask); + d=strrchr(c,'\\'); + d++; + strcpy(d,filename); + d=alloca(strlen(target)+strlen(filename)+10); + strcpy(d,target); + if (d[0]==0 || d[strlen(d)-1]!='\\') strcat(d,"\\"); + strcat(d,filename); + set_value(0,20,filename); + add_to_list(d); + cpy_file(c,d); + } + +static void copy_files(char *param) + { + struct find_t ft; + char *source_mask; + char *target; + int rc; + + target=strchr(param,' '); + if (target==NULL) return; + source_mask=alloca(target-param); + source_mask[target-param]=0; + strncpy(source_mask,param,target-param); + target++; + rc=_dos_findfirst(source_mask,_A_NORMAL,&ft); + while (rc==0) + { + copy_1_file(source_mask,ft.name,target); + rc=_dos_findnext(&ft); + } + _dos_findclose(&ft); + } + +char cascade_mkdir(char *path) + { + char *c; + char d; + + if (path[0]==0||path[1]==':' && path[2]==0) return 0; + if (!access(path,F_OK)) return 0; + c=strrchr(path,'\\'); + if (c==NULL) return 0; + *c=0; + d=cascade_mkdir(path); + *c='\\'; + if (d==1) return 1; + if (mkdir(path)!=0) return 1; + add_to_list(path); + return 0; + } + + +static char add_to_ini(char *params) + { + return fprintf(ini,"%s\n",params)<0; + } + +static char *commands[]= + { + COPY, + MKDIR, + INI, + }; + +static char (*calls[])(char *params)= + { + copy_files, + cascade_mkdir, + add_to_ini, + }; + + + +static char command_match(char *cmd,char *test,char **params) + { + while (*test) if (toupper(*cmd++)!=toupper(*test++)) return 0; + if (*cmd!=' ') return 0; + *params=cmd+1; + return 1; + } + + +char do_script(int section) + { + int pos; + int num; + int str_siz=str_count(script); + char *command; + + for(pos=0;pos"); + } + return s; + } + +char validate_path(char *path) + { + unsigned disk; + unsigned cdisk,lastdrv; + char *c,ll=0,tt=0,d; + + static char valid[]="$%'_@{}~`#()&-"; + + if (path==NULL || path[0]==0 || path[1]!=':' || path[2]!='\\') return 0; + disk=toupper(path[0]); + if (disk<'A' || disk>'Z') return 0; + _dos_getdrive(&cdisk); + disk-='@';_dos_setdrive(disk,&lastdrv); + _dos_getdrive(&lastdrv); + disk=(disk==lastdrv); + _dos_setdrive(cdisk,&lastdrv); + if (!disk) return 0; + c=path+2;ll=0; + while (*c) + { + d=toupper(*c); + if (d=='\\') + if (ll) return 0;else ll=1,tt=0; + else + if (d>='A' && d<='Z' || d>='0' && d<='9' || strchr(valid,d)!=NULL || d>127) ll=0; + else if (d=='.') if (tt) return 0;else tt=1; + else return 0; + c++; + } + if (ll) return 0; + return 1; + } + +void clean_up() + { + int i,cnt; + if (file_list==NULL) return; + cnt=str_count(file_list); + for(i=cnt-1;i>=0;i--) if (file_list[i]!=NULL) + { + if (remove(file_list[i])) rmdir(file_list[i]); + } + release_list(file_list); + file_list=NULL; + } + +void purge_file_list() + { + if (file_list==NULL) return; + release_list(file_list); + file_list=NULL; + } + +char cascade_delete(char ignore_sav) + { + struct find_t f; + int rc; + + rc=_dos_findfirst("*.*",_A_SUBDIR,&f); + while (rc==0) + { + if (f.attrib & _A_SUBDIR) + { + if (f.name[0]!='.') + { + chdir(f.name); + cascade_delete(ignore_sav); + chdir(".."); + rmdir(f.name); + } + } + else + { + char *c=strchr(f.name,'.'); + + if (c!=NULL) + { + strupr(c); + if (!ignore_sav || strncmp(c,".SAV",4)) remove(f.name); + } + else remove(f.name); + } + rc=_dos_findnext(&f); + } + return 0; + } diff --git a/INST/SETUPLIB.H b/INST/SETUPLIB.H new file mode 100644 index 0000000..7928d30 --- /dev/null +++ b/INST/SETUPLIB.H @@ -0,0 +1,22 @@ +char all_finder(); +char select_disk(); +char read_script(char *filename,char *source_path,char *target_path); +long check_size(int gr); +long get_disk_free(char disk); +void view_line(OBJREC *o); +char *get_cdrom(); +char get_max_res(); +char do_script(int); +void done_bar(); //define(...done_bar,max); +char cascade_mkdir(char *path); +char validate_path(char *path); +char cascade_delete(char ignore_sav); //maze soubory a podadresare. Pripadne ignoruje soubory SAV + +void clean_up(); //maze zkopirovane soubory a adresare +void purge_file_list(); +void add_to_list(char *name); + + +#define INST_MIN 0 +#define INST_MED 1 +#define INST_MAX 2 diff --git a/INST/SETVIDEO.C b/INST/SETVIDEO.C new file mode 100644 index 0000000..c5505b3 --- /dev/null +++ b/INST/SETVIDEO.C @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "setup.h" + +static void *xlat256=NULL; +static void *xlat16=NULL; + +static void create_xlats() + { + if (xlat256==NULL) xlat256=create_special_palette(); + if (xlat16==NULL) xlat16=create_blw_palette16(); + } + + +static void initgr_common() + { + register_ms_cursor(&sipka); + init_mysky(); + hranice_mysky(0,0,639,479); + update_mysky(); + schovej_mysku(); + bar(0,0,639,479); + showview(0,0,0,0); + } + +int initgr_auto() + { + int vmode; + create_xlats(); + vmode=2; + if (initmode32()) + { + vmode=1; + if (initmode256(xlat256)) + { + vmode=0; + initmode16(xlat16); + } + } + initgr_common(); + return vmode; + } + +int initgr_spec(int vmode) + { + int i=-1; + create_xlats(); + switch (vmode) + { + case 0:i=initmode_lo(xlat256);break; + case 1:i=initmode256(xlat256);break; + case 2:i=initmode32();break; + } + initgr_common(); + return i; + } + +void initgr_low() + { + create_xlats(); + initmode16(xlat16); + initgr_common(); + } + +void donegr() + { + closemode(); + done_mysky(); + } + +void kresli_okno(WINDOW *w) + { + int x,y; + int xs,ys,xsr,ysr; + int x1,y1,xs1,ys1; + int i,j; + + xsr=ramecky[0][0]; + ysr=ramecky[0][1]; + x1=w->x-12; + y1=w->y-12; + xs1=w->xs+24; + ys1=w->ys+24; + xs=xs1/xsr; + ys=ys1/ysr; + curcolor=w->color; + bar(w->x,w->y,w->x+w->xs,w->y+w->ys); + for(j=0,y=y1;jx; + y=waktual->y; + } + name; + highlight(&ctl,WINCOLOR); + ctl.bsize=2;ctl.ctldef=0; + x+=20;y+=20; + memcpy(fc,flat_color(0x7fe0),sizeof(FC_TABLE)); + fc[0]=0x0000; + if (x+xs>MAX_X-2) x=MAX_X-2-xs; + if (y+ys>MAX_Y-2) y=MAX_Y-2-ys; + p=create_window(x,y,xs,ys,WINCOLOR,&ctl); + q=desktop_add_window(p); + define(0,2,2,xs-5-20*(xs>=70),14,0,win_label,name); + ctl.bsize=1;ctl.ctldef=1; + o_end->autoresizex=1; + property(&ctl,vga_font,&fc,LABELCOLOR); + if (xs>=70) + { + define(1,1,1,19,16,1,button,"\x0f"); + property(NULL,icones,&icone_color,WINCOLOR);on_change(close_current); + } + return q; + } + +int def_dialoge(word x,word y,word xs, word ys, char *name,char modal) + { + CTL3D ctl; + FC_TABLE fc; + WINDOW *p; + int i; + + memcpy(fc,flat_color(0x7fe0),sizeof(FC_TABLE)); + if (modal & 0x2) + { + ctl.bsize=12; + xs=((xs+6)/12)*12; + ys=((ys+6)/12)*12; + } + else + memcpy(&ctl,def_border(2,WINCOLOR),sizeof(CTL3D)); + p=create_window(x,y,xs,ys,WINCOLOR,&ctl); + i=desktop_add_window(p); + if (modal & 1) set_window_modal(); + memcpy(&ctl,def_border(5,WINCOLOR),sizeof(CTL3D)); + if (name!=NULL) + { + define(0,2,2,xs-4,14,0,win_label,name); + o_end->autoresizex=1; + property(&ctl,vga_font,&fc,LABELCOLOR); + } + if (modal & 0x2) p->draw_event=kresli_okno; + return i; + } + +void def_listbox(int id,word x,word y,word xs,word ys,TSTR_LIST ls,int ofs,int color) + { + CTL3D b1,b2; + word black[]={0,0,0,0,0,0}; + + memcpy(&b1,def_border(1,0),sizeof(CTL3D)); + memcpy(&b2,def_border(5,WINCOLOR),sizeof(CTL3D)); + define(id+1,x+xs+4,y+18,15,ys-35,0,scroll_bar_v,0,10,1,0x0200); + property(&b2,NULL,NULL,WINCOLOR); + define(id+2,x+xs+4,y,14,14,0,scroll_button,-1,0,"\x4"); + property(&b1,icones,black,WINCOLOR);on_change(scroll_support); + define(id+3,x+xs+4,y+ys-14,14,14,0,scroll_button,1,10,"\6"); + property(&b1,icones,black,WINCOLOR);on_change(scroll_support); + define(id,x,y,xs,ys,0,listbox,ls,color,ofs); + property(&b2,NULL,NULL,WINCOLOR); + } + diff --git a/INST/SETVIDEO.H b/INST/SETVIDEO.H new file mode 100644 index 0000000..dce03e5 --- /dev/null +++ b/INST/SETVIDEO.H @@ -0,0 +1,6 @@ +int initgr_auto(); +void initgr_low(); +int initgr_spec(int vmode); +void donegr(); +int def_dialoge(word x,word y,word xs, word ys, char *name,char modal); +void def_listbox(int id,word x,word y,word xs,word ys,TSTR_LIST ls,int ofs,int color); diff --git a/INST/STUB.C b/INST/STUB.C new file mode 100644 index 0000000..c059d9b --- /dev/null +++ b/INST/STUB.C @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include +#define QUIET x + +/* Add environment strings to be searched here */ +char *paths_to_check[] = { + "DOS4GPATH", + "PATH"}; + +char *dos4g_path() +{ + static char fullpath[80]; + int i; + + for( i = 0; + i < sizeof( paths_to_check ) / sizeof( paths_to_check[0] ); i++ ) { + _searchenv( "dos4gw.exe", paths_to_check[i], fullpath ); + if( fullpath[0] ) return( &fullpath ); + } + for( i = 0; + i < sizeof( paths_to_check ) / sizeof( paths_to_check[0] ); i++ ) { + _searchenv( "dos4g.exe", paths_to_check[i], fullpath ); + if( fullpath[0] ) return( &fullpath ); + } + return( "dos4gw.exe" ); +} + +main( int argc, char *argv[] ) +{ + char *av[4]; + auto char cmdline[128]; + int i; + av[0] = dos4g_path(); /* Locate the DOS/4G loader */ + av[1] = argv[0]; /* name of executable to run */ + av[2] = getcmd( cmdline ); /* command line */ + av[3] = NULL; /* end of list */ +#ifdef QUIET + putenv( "DOS4G=QUIET" ); /* disables DOS/4G Copyright banner */ +#endif + printf("Instalator Br ny Skeldalu (C)1997 Napoleon gameS Nahr v m... \n"); + i=spawnvp(P_WAIT, av[0], av ); + if (i==254) + execl(av[0],av[0],"SKELDAL.EXE",NULL);else exit(0); + puts( "Chyba pri nacitani extenderu:" ); + puts( av[0] ); + puts( "\nZkontrolujte zda-li je k dosazeni na aktualnim adresari\n" + "popripade specifikujte jeho v cestu v systemove promenne:\n" + "SET DOS4GPATH=disk:\\cesta\n"); + exit( 1 ); /* indicate error */ +} diff --git a/INST/TEXTLIB.ASM b/INST/TEXTLIB.ASM new file mode 100644 index 0000000..3ec6511 --- /dev/null +++ b/INST/TEXTLIB.ASM @@ -0,0 +1,101 @@ +.model small +.386 + +SEGB800 equ 0b8000h + +_TEXT segment byte public 'CODE' use32 + assume CS:_TEXT + assume DS:DGROUP + +public load_font_ +load_font_: ;esi font + mov esi,offset fonttable + mov edx,3c4h + mov eax,0402h + out dx,ax + mov eax,0704h + out dx,ax + Mov edx,3ceh + mov eax,0204h + out dx,ax + mov eax,0005h + out dx,ax + mov eax,0406h + out dx,ax + mov edi,0xA0000h + mov edx,256 +lfOpk: mov ecx,16 + rep movsb + add edi,16 + dec edx + jne lfopk + mov edx,3c4h + mov eax,0302h + out dx,ax + mov eax,0304h + out dx,ax + Mov edx,3ceh + mov eax,0004h + out dx,ax + mov eax,1005h + out dx,ax + mov eax,0E06h + out dx,ax + ret + +public set_font_8x8_ +set_font_8x8_: + cli + mov edx,3d4h + mov eax,0100h + out dx,ax + mov edx,3c4h + mov al,1 + out dx,al + inc edx + in al,dx + or al,1 + out dx,al + mov edx,03dah + in al,dx + mov edx,03c0h + mov al,13h + out dx,al + mov al,0 + out dx,ax + mov al,32 + out dx,al + mov edx,3d4h + mov eax,0300h + out dx,ax + sti + ret + +public turn_flashing_ ;ebx - ON/OFF +turn_flashing_: + mov eax,1003h + int 10h + ret + + +public get_window_size_ ;eax,edx-velikost +get_window_size_: + imul eax,edx + shl eax,1 + add eax,4 + ret + +public save_window_ ;eax,edx-pozice + ;ecx,ebx-velikost + ;edi - buffer +save_window_ + stosb + imul eax,160 + lea eax,[eax+edx*2] + lea esi,[eax+SEGB800] + mov al,dl + stosb + mov al,bl + mov ah,cl + stosw + mov edx,ebx diff --git a/INST/TEXTLIB.C b/INST/TEXTLIB.C new file mode 100644 index 0000000..fd40910 --- /dev/null +++ b/INST/TEXTLIB.C @@ -0,0 +1,4 @@ + + + + diff --git a/LIBS/ADDTEXT.C b/LIBS/ADDTEXT.C new file mode 100644 index 0000000..14b9222 --- /dev/null +++ b/LIBS/ADDTEXT.C @@ -0,0 +1,120 @@ +#include +#include +#include "memman.c" +#include "strlite.c" + + +TSTR_LIST ls_origin=NULL; +TSTR_LIST ls_new=NULL; + +static void load_error_msg(int err,char *filename) + { + switch (err) + { + case -1: puts ("Source or target file not found");break; + case -2: puts ("Unexcepted EOF");break; + case -3: puts ("Internal error in strlite.c");break; + default: printf("Error in string table at line %d.\n",err); + } + printf("File:%s\n",filename); + exit(1); + } + +void load_lists(char *filename1,char *filename2) + { + int err; + + err=load_string_list(&ls_new,filename1); + if (err) load_error_msg(err,filename1); + err=load_string_list(&ls_origin,filename2); + if (err) load_error_msg(err,filename2); + } + + +char *create_backup(char *filename) + { + char *c,*d; + + c=getmem(strlen(filename)+5);strcpy(c,filename); + d=strrchr(c,'.');if (d==NULL) d=strchr(c,0); + strcpy(d,".bak"); + remove(c); + rename(filename,c); + return c; + } + +void spoj_stringtable() + { + int i; + int cnt=str_count(ls_new); + for(i=0;i +#include +#include +#include +#include +#include +#include + +char copy_path[500]; +char *adv_name; + +char _change_disk(unsigned znak) + { + unsigned total; + znak-='@'; + _dos_setdrive(znak,&total); + _dos_getdrive(&total); + return total==znak; + } + +char disk_finder() + { + static struct find_t ft; + int err; + + if (!access("SKELDAL.EXE",F_OK) && !access("ADV",F_OK)) return 1; + err=_dos_findfirst("*.*",_A_SUBDIR,&ft); + while (!err) + { + if (ft.attrib & _A_SUBDIR && strcmp(ft.name,".") && strcmp(ft.name,"..")) + { + chdir(ft.name); + if (disk_finder()) return 1; + chdir(".."); + } + err=_dos_findnext(&ft); + } + return 0; + } + +char find_path(char *path) + { + char *oldpath; + unsigned pismeno='C'; + + cputs("Hledam...\r"); + oldpath=getcwd(NULL,PATH_MAX); + for(pismeno='C';pismeno<='Z';pismeno++) + { + _change_disk(pismeno); + chdir(".."); + if (disk_finder()==1) + { + getcwd(path,PATH_MAX); + chdir(oldpath);_change_disk(oldpath[0]); + free(oldpath); + return 1; + } + } + chdir(oldpath);_change_disk(oldpath[0]); + free(oldpath); + return 1; + } + + +void main(int argc,char **argv) + { + char temp[550]; + char rep; + if (argc<2) + { + puts("Nespravne parametry!\n" + "\n" + "Pouziti ADVINST [jmeno]\n" + "\n" + "jmeno = Nazev dobrodruzstvi bez pripony"); + return; + } + adv_name=argv[1]; + sprintf(temp,"%s.adv",adv_name); + if (access(adv_name,F_OK) && access(temp,F_OK)) + { + printf("Nemohu najit zadne dobrodruzstvi s timto jmenem (%s)!\n",adv_name); + return; + } + do + { + printf("Vypiste celou cestu, kde lezi hra (napr: c:\\hry\\skeldal)\n" + "Pokud vlozte otaznik (?), instalator se pokusi hru na disku vyhledat\n" + "Pokud stisknete pouze , instalator se ukonci\n" + ">"); + gets(copy_path); + if (copy_path[0]=='?') + { + find_path(copy_path); + printf("\nInstalator nasel hru na ceste: %s\n\n",copy_path); + } + if (copy_path[0]==0) return; + sprintf(temp,"%s\\skeldal.exe",copy_path); + rep=access(temp,F_OK); + if (rep) puts("Vami vlozena cesta neni spravna!\n"); + else + { + sprintf(temp,"%s\\adv\\%s",copy_path,adv_name); + if (access(temp,F_OK))if (mkdir(temp)!=0) printf("Nedokazal jsem vytvorit adresar %s\n\n\n",temp),rep=1; + } + } + while(rep); + sprintf(temp,"copy %s.adv %s > nul",adv_name,copy_path); + puts(temp); + system(temp); + sprintf(temp,"copy %s\\*.* %s\\adv\\%s > nul",adv_name,copy_path,adv_name); + puts(temp); + system(temp); + sprintf(temp,"%s.bat",adv_name); + if (access(temp,F_OK)==0) + { + sprintf(temp,"%s.bat %s",adv_name,copy_path); + puts(temp); + system(temp); + } + chdir(copy_path); + puts("Instalace uspesna!"); + printf("Nove dobrodruzstvi spustis prikazem SKELDAL %s.adv\n",adv_name); + puts("Chces si nyni nove dobrodruzstvi vyzkouset? ANO/NE (cokoliv/N)"); + if (toupper(getche())=='N') return; + sprintf(temp,"SKELDAL %s.adv",adv_name); + system(temp); + } + + + diff --git a/LIBS/BASICOBJ.C b/LIBS/BASICOBJ.C new file mode 100644 index 0000000..4a06672 --- /dev/null +++ b/LIBS/BASICOBJ.C @@ -0,0 +1,1332 @@ +#include +// toto je include soubor, jenz je pouzit v knihovne GUI.C + +#include "types.h" +#include +#include +#include +#include +#include "memman.h" +#include "event.h" +#include "devices.h" +#include "bmouse.h" +#include "bgraph.h" +#include "gui.h" +#include "basicobj.h" + +#define MEMTEXT "Pamt: " + +#define E_STATUS_LINE 60 + +//FC_TABLE f_bila={0xffff,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; + +void highlight(CTL3D *c,word color) + { + c->light=color<<1; + if (c->light & 0x0020) {c->light&=~RGB555(0,0,31);c->light|=RGB555(0,0,31);} + if (c->light & 0x0400) {c->light&=~RGB555(0,31,0);c->light|=RGB555(0,31,0);} + if (c->light & 0x8000) {c->light&=~RGB555(31,0,0);c->light|=RGB555(31,0,0);} + c->shadow=color; + c->shadow&=RGB555(30,30,31); + c->shadow>>=1; + } + + +CTL3D *def_border(int btype,int color) + { + static CTL3D ctl; + + highlight(&ctl,color); + switch (btype) + { + case 0:ctl.bsize=0; + case 1:ctl.light=color;ctl.shadow=color;ctl.bsize=1;break; + case 2:ctl.bsize=2;ctl.ctldef=0;break; + case 3:ctl.bsize=2;ctl.ctldef=3;break; + case 4:ctl.bsize=1;ctl.ctldef=0;break; + case 5:ctl.bsize=1;ctl.ctldef=1;break; + case 6:ctl.bsize=2;ctl.ctldef=1;break; + case 7:ctl.bsize=2;ctl.ctldef=2;break; + } + return &ctl; + } + +void sample_init(OBJREC *o,char *title) + { + title=get_title(title); + o->userptr=(void *)getmem(strlen(title)+1); + strcpy((char *)o->userptr,title); + } + + +void sample_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + x2;y2; + position(x1,y1); + outtext((char *)o->userptr); + } + +void mid_label_draw(int x1,int y1,int x2, int y2,OBJREC *o) + { + x2;y2; + set_aligned_position((x1+x2)/2,y1,1,0,(char *)o->userptr); + outtext((char *)o->userptr); + } + + +void sample_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + o; + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->tl1) exit_wait=1; + } + } + + +void sample(OBJREC *o) + { + o->runs[0]=sample_init; + o->runs[1]=sample_draw; + o->runs[2]=sample_event; + //o->runs[3]=sample_done; + } + +//------------------------------------------ +void button_init(OBJREC *o,char *title) + { + char *v; + title=get_title(title); + o->userptr=(void *)getmem(strlen(title)+1); + strcpy((char *)o->userptr,title); + v=(char *)o->data; + *v=0; + } + +void button_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + CTL3D x; + char w; + + bar(x1,y1,x2,y2); + highlight(&x,o->color); + w=*(char *)o->data; + x.bsize=2-w; + x.ctldef=(w<<1)+w; + draw_border(x1+2,y1+2,x2-x1-4,y2-y1-4,&x); + set_aligned_position(((x1+x2)>>1)+(w<<1),((y1+y2)>>1)+(w<<1),1,1,(char *)o->userptr); + outtext((char *)o->userptr); + } + +void button_draw2(int x1,int y1,int x2,int y2,OBJREC *o) + { + CTL3D x; + char w; + + bar(x1,y1,x2,y2); + highlight(&x,o->color); + w=*(char *)o->data; + x.bsize=1; + x.ctldef=(w<<1)+w; + draw_border(x1+1,y1+1,x2-x1-2,y2-y1-2,&x); + if (!w) + { + curcolor=x.light;hor_line(x1,y1,x2);hor_line(x1,y1+1,x2); + curcolor=x.shadow;hor_line(x1,y2,x2);hor_line(x1,y2-1,x2); + } + set_aligned_position(((x1+x2)>>1)+(w<<1),((y1+y2)>>1)+(w<<1),1,1,(char *)o->userptr); + outtext((char *)o->userptr); + } + + +void button_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x06) + { + if (ms->tl1) + { + *(char *)o->data=1; + redraw_object(o); + } + else if (*(char *)o->data) + { + *(char *)o->data=0; + redraw_object(o); + set_change(); + } + } + } + + if (msg->msg==E_GET_FOCUS || msg->msg==E_LOST_FOCUS) + { + *(char *)o->data=0; + redraw_object(o); + } + } + + + +void button(OBJREC *o) + { + o->runs[0]=button_init; + o->runs[1]=button_draw; + o->runs[2]=button_event; + //o->runs[3]=button_done; + o->datasize=1; + } + +void button2(OBJREC *o) + { + o->runs[0]=button_init; + o->runs[1]=button_draw2; + o->runs[2]=button_event; + //o->runs[3]=button_done; + o->datasize=1; + } + + +//------------------------------------------ + +void draw_status_line(char *c) + { + static word *font; + static FC_TABLE color; + static word backgr; + static word ysmax=0,y; + word ysize; + CTL3D ctl; + + if (c==NULL) + { + backgr=curcolor; + memcpy(&color,&charcolors,sizeof(charcolors)); + font=curfont; + return; + } + + schovej_mysku(); + curfont=font; + ysize=text_height(c); + if (ysmax>ysize) ysize=ysmax;else + ysmax=ysize; + + highlight(&ctl,backgr); + ctl.bsize=2; + ctl.ctldef=0; + curcolor=backgr; + memcpy(&charcolors,&color,sizeof(charcolors)); + y=SCR_WIDTH_Y-ysize-3; + desktop_y_size=y-3; + bar(0,y,SCR_WIDTH_X-1,SCR_WIDTH_Y-1); + draw_border(2,y,SCR_WIDTH_X-5,ysize,&ctl); + while (text_width(c)>SCR_WIDTH_X) + { + char *p; + + p=strchr(c,'\0'); + *(--p)='\0'; + if (p=c) break; + } + position(5,y);outtext(c); + ukaz_mysku(); + showview(0,y-2,SCR_WIDTH_X-1,ysize+5); + } + +void *status_mem_info(EVENT_MSG *msg) + { + char *c; + long l; + static char memtext[]=MEMTEXT; + MEMORYSTATUS mem; + + if (msg->msg==E_INIT) return &status_mem_info; + c=(char *)msg->data; + strcpy(c,memtext); + c+=strlen(memtext); + get_mem_info(&mem); + l=mem.dwAvailPageFile; + sprintf(c,"%d KB ",l/1024); + c=strchr(c,'\0'); + msg->data=(void *)c; + return NULL; + } + +void *status_idle(EVENT_MSG *msg) + { + if (msg->msg==E_INIT) return &status_idle; + send_message(E_STATUS_LINE,msg->msg); + return NULL; + } + +void status_line(EVENT_MSG *msg,T_EVENT_ROOT **user_data) + { + T_EVENT_ROOT **p; + static char st_line[256],oldline[256]={"\0"}; + EVENT_MSG tg; + static char recurse=1; + + if(msg->msg==E_INIT) + if (recurse) + { + T_EVENT_ROOT *p; + recurse=0; + send_message(E_ADD,E_IDLE,status_idle); + send_message(E_ADD,E_REDRAW,status_idle); + p=NULL; + *user_data=p; + draw_status_line(NULL); + recurse=1; + return; + } + else return; + shift_msg(msg,tg); + if (tg.msg==E_REDRAW) + { + draw_status_line(oldline); + return; + } + p=user_data; + if (tg.msg==E_IDLE) + { + EVENT_MSG msg; + + msg.msg=E_IDLE; + msg.data=&st_line; + enter_event(p,&msg); + if (strcmp(st_line,oldline)) + { + draw_status_line(st_line); + strcpy(oldline,st_line); + } + } + else + tree_basics(p,&tg); + return; + } + +void *mouse_xy(EVENT_MSG *msg) + { + char *c; + + if (msg->msg==E_INIT) return &mouse_xy; + c=(char *)msg->data; + sprintf(c," X: %d Y: %d",ms_last_event.x,ms_last_event.y); + c=strchr(c,'\0'); + msg->data=(void *)c; + return NULL; + } + +void *show_time(EVENT_MSG *msg) + { + char *c; + time_t t; + struct tm cas; + + if (msg->msg==E_INIT) return &show_time; + c=(char *)msg->data; + t=time(NULL); + cas=*localtime(&t); + + sprintf(c,"%02d:%02d:%02d ",cas.tm_hour,cas.tm_min,cas.tm_sec); + c=strchr(c,'\0'); + msg->data=(void *)c; + return NULL; + } +//------------------------------------------ + +void win_label_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + bar(x1,y1,x2,y2); + set_aligned_position(x1+5,(y1+y2)/2,0,1,(char *)o->userptr); + outtext((char *)o->userptr); + } + +void xor_rectangle(int x,int y,int xs,int ys) + { + curcolor=RGB555(31,31,31); + if (x<0) x=0; + if (y<0) y=0; + if (x+xs>=SCR_WIDTH_X) xs=SCR_WIDTH_X-x-1; + if (y+ys>=SCR_WIDTH_Y) ys=SCR_WIDTH_Y-y-1; + schovej_mysku(); + hor_line_xor(x,y,x+xs); + ver_line_xor(x,y,y+ys); + if (xs && ys) + { + hor_line_xor(x,y+ys,x+xs); + ver_line_xor(x+xs,y,y+ys); + } + ukaz_mysku(); + showview(x,y,x+xs,4); + showview(x,y,4,ys+4); + if (xs && ys) + { + showview(x,y+ys,x+xs,4); + showview(x+xs,y,4,ys+4); + } + } + +void win_label_move(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + static char run=0; + static word xref,yref; + static WINDOW w; + static moved=0; + static drawed=0; + + o; + if (msg->msg==E_INIT) return; + if (msg->msg==E_TIMER) + { + send_message(E_TIMER); + if (!drawed) + if (!moved) + { + drawed=1; + redraw_desktop(); + moved=0; + } + else + { + drawed=0; + moved=0; + } + } + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (run) + { + //xor_rectangle(w.x,w.y,w.xs,w.ys); + if (ms->event_type & 4) + { + run=0; + redraw_desktop(); + send_message(E_DONE,E_MOUSE,win_label_move); + msg->msg=-1; + return; + } + w.x=ms->x-xref; + w.y=ms->y-yref; + check_window(&w); + //xor_rectangle(w.x,w.y,w.xs,w.ys); + waktual->x=w.x; + waktual->y=w.y; + waktual->xs=w.xs; + waktual->ys=w.ys; + moved=1;drawed=0; + redraw_window(); + redraw_desktop(); + } + else + if (ms->event_type & 2) + { + run=1; + memcpy(&w,waktual,sizeof(WINDOW)); + //xor_rectangle(w.x,w.y,w.xs,w.ys); + xref=ms->x-waktual->x; + yref=ms->y-waktual->y; + send_message(E_ADD,E_MOUSE,win_label_move); + freeze_on_exit=1; + } + } + if (msg->msg==E_LOST_FOCUS && run) + { + run=0; + redraw_desktop(); + send_message(E_DONE,E_MOUSE,win_label_move); + msg->msg=-1; + return; + } +msg->msg=-1; +return; + } + + +void win_label(OBJREC *o) + { + o->runs[0]=sample_init; + o->runs[1]=win_label_draw; + o->runs[2]=win_label_move; + //o->runs[3]=button_done; + o->datasize=0; + } + +//------------------------------------------ + +void check_box_draw(int x1,int y1, int x2, int y2,OBJREC *o) + { + int x3; + + x1+=1;y1+=1;x2-=1;y2-=1; + x3=x1+(y2-y1); + draw_border(x1,y1,x3-x1,y2-y1,def_border(4,curcolor)); + bar(x1,y1,x3,y2); + if (*(char *)o->data & 1) + { + curcolor=0x0000; + line(x1,y1,x3,y2);line(x1+1,y1,x3,y2-1);line(x1,y1+1,x3-1,y2); + line(x1,y2,x3,y1);line(x1+1,y2,x3,y1+1);line(x1,y2-1,x3-1,y1); + } + if (*(char *)o->data & 0x80) + { + curcolor=0x0000; + hor_line(x1,y1,x3);ver_line(x3,y1,y2); + ver_line(x1,y1,y2);hor_line(x1,y2,x3); + } + else + { + set_aligned_position(x3+5,(y2+y1)/2,0,1,(char *)o->userptr); + outtext((char *)o->userptr); + } + } + +void check_box_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x06) + { + if (ms->tl1) + { + *(char *)o->data|=0x80; + redraw_object(o); + } + else if (*(char *)o->data) + { + *(char *)o->data^=0x1; + *(char *)o->data&=0x1; + redraw_object(o); + set_change(); + } + } + } + + if (msg->msg==E_GET_FOCUS || msg->msg==E_LOST_FOCUS) + { + *(char *)o->data&=0x1; + redraw_object(o); + } + } + + +void check_box(OBJREC *o) + { + o->runs[0]=sample_init; + o->runs[1]=check_box_draw; + o->runs[2]=check_box_event; + o->datasize=4; + } + +//------------------------------------------ +void radio_butts_init(OBJREC *o,long *params) + { + char *c,*z; + long cnt=0,*q,*d; + int i; + + d=params; + for (i=0;i<*params;i++) + { + d+=1; + c=get_title(d); + cnt+=strlen(c);cnt++; + } + q=(long *)getmem(cnt+8); + o->userptr=(void *)q; + *q++=1;*q++=*params; + d=params; + z=(char *)q; + for (i=0;i<*params;i++) + { + d+=1; + c=get_title(d); + strcpy(z,c); + z=strchr(z,'\0');z++; + } + } + +void radio_butts_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + int step,size,sizpul,i,cr; + long *params; + char *texts; + CTL3D ctl; + + cr=curcolor; + highlight(&ctl,curcolor); + params=(long *)o->userptr; + if (*params) bar(x1,y1,x2,y2); + step=(y2-y1)/(*(params+1)); + size=(step*9)/10; + sizpul=size>>1; + + texts=(char *)(params+2); + for (i=0;i<*(params+1);i++,y1+=step) + { + int j; + curcolor=ctl.shadow; + line(x1+sizpul,y1,x1,y1+sizpul); + line(x1,y1+sizpul,x1+sizpul,y1+size-1); + curcolor=ctl.light; + line(x1+sizpul+1,y1,x1+size,y1+sizpul); + line(x1+size,y1+sizpul,x1+sizpul+1,y1+size-1); + if (*(long *)o->data==i) curcolor=0;else curcolor=cr; + for (j=0;j<3;j++) + { + hor_line(x1+sizpul-j,y1+sizpul-2+j,x1+sizpul+j); + hor_line(x1+sizpul-j,y1+sizpul+2-j,x1+sizpul+j); + } + if (*params) + { + set_aligned_position(x1+size+5,y1+sizpul,0,1,texts); + outtext(texts); + texts=strchr(texts,'\0')+1; + } + + } + } + +void radio_butts_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + int sel; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x02) + { + sel=(ms->y-o->locy)/(o->ys/(*((long *)o->userptr+1))); + if (sel>=*((long *)o->userptr+1)) sel=*((long *)o->userptr+1)-1; + *(long *)o->data=sel; + *(long *)o->userptr=0; + redraw_object(o); + *(long *)o->userptr=1; + set_change(); + } + } + + } + + +void radio_butts(OBJREC *o) + { + o->runs[0]=radio_butts_init; + o->runs[1]=radio_butts_draw; + o->runs[2]=radio_butts_event;; + o->datasize=4; + } + +//------------------------------------------ + + + +void toggle_button_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + static char toggle_exit=0; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x06) + { + if (ms->tl1) + { + *(char *)o->data^=1; + redraw_object(o); + toggle_exit=1; + } + else if (toggle_exit) + { + set_change(); + toggle_exit=0; + } + } + } + + if ((msg->msg==E_GET_FOCUS || msg->msg==E_LOST_FOCUS)&&toggle_exit) + { + *(char *)o->data^=1; + redraw_object(o); + toggle_exit=0; + } + } + + + +void toggle_button(OBJREC *o) + { + o->runs[0]=button_init; + o->runs[1]=button_draw; + o->runs[2]=toggle_button_event; + o->datasize=1; + } + +//------------------------------------------ + +void input_line_init(OBJREC *o,int *len) + { + o->datasize=(*len)+1; + o->userptr=malloc(20); + memset(o->userptr,0,20); + memcpy(o->userptr,len,4); + memcpy((int *)o->userptr+2,len+1,12); + } + +void input_line_draw(int x1,int y1, int x2, int y2, OBJREC *o) + { + char d[2]=" \0"; + int x; + char *c; + int len; + int shift; + + bar(x1,y1,x2,y2); + position(x1,y1); + c=(char *)o->data; + if (!*c) return; + len=strlen(c); + shift=*((int *)o->userptr+1); + if (shift>=len) shift=0; + c+=shift; + d[0]=*c++;x=x1+text_width(d); + while (xuserptr; + start=len+1; + c=(char *)o->data; + slen=strlen(c); + switch (msg->msg) + { + case E_GET_FOCUS:cursor=0;save=(char *)getmem(*len+1); + strcpy(save,c);clear_kontext=1;break; + case E_LOST_FOCUS:cursor=0;*start=0;free(save);redraw_object(o);break; + case E_CURSOR_TICK: + { + int xpos,i,j=-1,d; + + do + { + xpos=0;j++; + for (i=*start;i=o->xs) (*start)+=1; + if (xpos==0) (*start)-=1; + if (*start<0) *start=0; + } + while ((xpos==0 || xpos>=o->xs)&& cursor); + if (j) redraw_object(o); + xor_rectangle(o->locx+xpos,o->locy,1,o->ys); + };break; + case E_MOUSE: + { + MS_EVENT *ms;int msx; + + ms=get_mouse(msg); + msx=ms->x-o->locx; + if (ms->event_type & 2) + { + int xpos; + + xpos=0; + for (cursor=*start;cursormsx) break; + } + redraw_object(o); + } + } + break; + case E_KEYBOARD: + { + char key; + + cancel_event(); + key=(*(int *)msg->data) & 0xff; + if (!key) + switch (*(int *)msg->data >> 8) + { + case 'M':if (cursor0) cursor--;break; + case 'S':if (cursor0) {strcpy(&c[cursor-1],&c[cursor]);cursor--;}break; + case 0:break; + case 13:break; + case 27:strcpy(c,save);slen=strlen(c);if (cursor>slen) cursor=slen;break; + default:if (key>=' ') if (slen<*len || clear_kontext) + { + int i; + + if (clear_kontext) + {*c='\0';cursor=0;slen=0;} + for (i=slen+1;i>cursor;i--) c[i]=c[i-1]; + c[cursor++]=key; + } + } + if (!cursor) *start=0; + redraw_object(o); + msg->msg=E_CURSOR_TICK; + input_line_event(msg,o); + clear_kontext=0; + msg->msg=-1; + } + } + } + + + + + +void input_line(OBJREC *o) + { + o->runs[0]=input_line_init; + o->runs[1]=input_line_draw; + o->runs[2]=input_line_event; + } + + +//------------------------------------------------------------- +void label(OBJREC *o) + { + o->runs[0]=sample_init; + o->runs[1]=sample_draw; + } + +void mid_label(OBJREC *o) + { + o->runs[0]=sample_init; + o->runs[1]=mid_label_draw; + } +//------------------------------------------------------------- + +typedef struct scr_button + { + int step; + int maxvalue; + char *title; + }SCR_BUTTON; + +void scroll_button_init(OBJREC *o,int *param) + { // int step, int maxvalue,char *title + char *v; + SCR_BUTTON *p; + + o->userptr=getmem(sizeof(SCR_BUTTON)); + p=(SCR_BUTTON *)o->userptr; + p->step=*param++; + p->maxvalue=*param++; + p->title=(char *)*param++; + v=(char *)o->data; + *v=0; + } + + + +void scroll_button_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + CTL3D x; + char w; + SCR_BUTTON *param; + + param=(SCR_BUTTON *)o->userptr; + bar(x1,y1,x2,y2); + highlight(&x,o->color); + w=*(char *)o->data; + x.bsize=2-w; + x.ctldef=(w<<1)+w; + draw_border(x1+2,y1+2,x2-x1-4,y2-y1-4,&x); + set_aligned_position(((x1+x2)>>1)+(w<<1),((y1+y2)>>1)+(w<<1),1,1,param->title); + outtext(param->title); + } + +void scroll_button_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (ms->event_type & 0x0e) + { + if (ms->tl1 || ms->event_type & 0x8) + { + *(char *)o->data=1; + redraw_object(o); + set_change(); + } + } + } + if (msg->msg==E_TIMER && *(char *)o->data ) + if (ms_last_event.tl1) set_change(); + else if (!ms_last_event.tl2) + { + *(char *)o->data=0; + redraw_object(o); + } + + if (msg->msg==E_GET_FOCUS || msg->msg==E_LOST_FOCUS) + { + *(char *)o->data=0; + redraw_object(o); + } + } + +void scroll_button(OBJREC *o) + { + o->runs[0]=scroll_button_init; + o->runs[1]=scroll_button_draw; + o->runs[2]=scroll_button_event; + o->datasize=1; + } + + +//------------------------------------------------------------- +typedef struct scr_bar + { + int minvalue; + int maxvalue; + int parview; + int bgcolor; + int barsize; + int stepsize; + }SCR_BAR; + +void scroll_bar_init(OBJREC *o,int *param) + { + SCR_BAR *p; + + o->userptr=getmem(sizeof(SCR_BAR)); + p=(SCR_BAR *)o->userptr; + p->minvalue=*param++; + p->maxvalue=*param++; + p->parview=*param++; + p->bgcolor=*param++; + p->barsize=10; + p->stepsize=10; + } + +void scroll_bar_v_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + int barsize; + int wsize; + int valsize; + SCR_BAR *p; + int *d; + CTL3D ctl; + int y; + + + p=(SCR_BAR *)o->userptr; + d=(int *)o->data; + valsize=p->maxvalue-p->minvalue+p->parview; + wsize=y2-y1; + barsize=valsize?wsize*p->parview/valsize:10; if (barsize<2) barsize=2; + if (barsize>wsize) barsize=wsize; + wsize-=barsize; + curcolor=p->bgcolor; + bar(x1,y1,x2,y2); + curcolor=o->color; + highlight(&ctl,o->color);ctl.bsize=2;ctl.ctldef=0; + y=valsize?(*d-p->minvalue)*(wsize+barsize)/valsize:0; + p->stepsize=valsize?wsize/valsize:0; + if (y>wsize) y=wsize; + if (y<0) y=0; + y+=y1; + draw_border(x1+2,y+2,(x2-x1)-4,barsize-4,&ctl); + if (barsize>4)bar(x1+2,y+2,x2-2,y+barsize-2); + p->barsize=barsize; + } + +void scroll_bar_v_event(EVENT_MSG *msg,OBJREC *o) + { + SCR_BAR *p; + int *d; + int _d; + + p=(SCR_BAR *)o->userptr; + d=(int *)o->data; + switch (msg->msg) + { + case E_MOUSE: + { + int y; + MS_EVENT *ms; + + ms=get_mouse(msg); + y=(ms->y+(p->stepsize>>1)-o->locy-(p->barsize>>1)); + if (ms->tl1) + { + if (o->ys<=p->barsize) _d=p->minvalue; else + _d=y*(p->maxvalue-p->minvalue)/(o->ys-p->barsize)+p->minvalue; + if (_d>p->maxvalue) _d=p->maxvalue; + if (_dminvalue) _d=p->minvalue; + if (_d!=*d) + { + *d=_d; + redraw_object(o); + set_change(); + } + } + } + break; + case E_CONTROL: + { + int *q; + + q=msg->data; + p->minvalue=*q++; + p->maxvalue=*q++; + p->parview=*q++; + } + break; + + } + } + +void scroll_bar_v(OBJREC *o) + { + o->runs[0]=scroll_bar_init; + o->runs[1]=scroll_bar_v_draw; + o->runs[2]=scroll_bar_v_event; + o->datasize=4; + } + +//------------------------------------------------------------- +void scroll_support() + { + int id,x; + SCR_BAR *p; + SCR_BUTTON *q; + OBJREC *o,*r; + + + id=o_aktual->id; + id=(id/10)*10; + o=find_object(waktual,id); + p=(SCR_BAR *)o->userptr; + q=(SCR_BUTTON*)o_aktual->userptr; + x=f_get_value(0,id); + x+=q->step; + if (q->step<0) + if (xminvalue) x=p->minvalue; + if (q->step>0) + if (x>p->maxvalue) x=p->maxvalue; + set_value(0,id,&x); + r=o_aktual; + o_aktual=o; + o->events[3](); + o_aktual=r; + } +//------------------------------------------------------------- + +void scroll_bar_h_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + int barsize; + int wsize; + int valsize; + SCR_BAR *p; + int *d; + CTL3D ctl; + int x; + + + p=(SCR_BAR *)o->userptr; + d=(int *)o->data; + valsize=p->maxvalue-p->minvalue; + wsize=x2-x1; + barsize=wsize*p->parview/valsize; + if (barsize>wsize) barsize=wsize;if (barsize<2) barsize=2; + wsize-=barsize; + curcolor=p->bgcolor; + bar(x1,y1,x2,y2); + curcolor=o->color; + highlight(&ctl,o->color);ctl.bsize=2;ctl.ctldef=0; + x=(*d-p->minvalue)*wsize/valsize; + p->stepsize=wsize/valsize; + if (x>wsize) x=wsize; + if (x<0) x=0; + x+=x1; + draw_border(x+2,y1+2,barsize-4,(y2-y1)-4,&ctl); + if (barsize>4)bar(x+2,y1+2,x+barsize-2,y2-2); + p->barsize=barsize; + } + +void scroll_bar_h_event(EVENT_MSG *msg,OBJREC *o) + { + SCR_BAR *p; + int *d; + int _d; + + p=(SCR_BAR *)o->userptr; + d=(int *)o->data; + switch (msg->msg) + { + case E_MOUSE: + { + int x; + MS_EVENT *ms; + + ms=get_mouse(msg); + x=(ms->x+(p->stepsize>>1)-o->locx-(p->barsize>>1)); + if (ms->tl1) + { + if (o->xs<=p->barsize) _d=p->minvalue; else + _d=x*(p->maxvalue-p->minvalue)/(o->xs-p->barsize)+p->minvalue; + if (_d>p->maxvalue) _d=p->maxvalue; + if (_dminvalue) _d=p->minvalue; + if (_d!=*d) + { + *d=_d; + redraw_object(o); + set_change(); + } + } + } + } + } + + + + + + void scroll_bar_h(OBJREC *o) + { + o->runs[0]=scroll_bar_init; + o->runs[1]=scroll_bar_h_draw; + o->runs[2]=scroll_bar_h_event; + o->datasize=4; + + } + + +//------------------------------------------------------------- + + + +#define MSG_SIZE (SCR_WIDTH_X*3/4) +#define MSG_L_MARGIN 10 +#define MSG_R_MARGIN 50 +#define MSG_A_MARGIN (MSG_L_MARGIN+MSG_R_MARGIN) +#define MSG_COLOR RGB555(15,0,0) +#define MSG_F_COLOR RGB555(31,31,0) + +word *msg_box_font; +word *msg_icn_font; + + +int msg_box(char *title, char icone, char *text, ... ) + { + int winx,winy,xp,yp,txt_h; + int txt_max,temp1,temp2,i; + char buf[256]; + char *p; + CTL3D *ctl; + char **c; + FC_TABLE cl; + + curfont=msg_box_font; + ctl=def_border(2,MSG_COLOR); + winx=text_width(text)+MSG_A_MARGIN; + winy=30; + desktop_add_window(create_window(0,0,winx,300,MSG_COLOR,ctl)); + buf[1]='\0';buf[0]=icone; + xp=text_width(buf); + define(-1,(MSG_R_MARGIN>>1)-(xp>>1),20,xp,text_height(buf),1,label,buf); + cl[1]=ctl->light; + cl[0]=ctl->shadow; + property(NULL,msg_icn_font,&cl,MSG_COLOR); + curfont=msg_box_font; + default_font=curfont; + if (winx>MSG_SIZE) winx=MSG_SIZE; + c=&text;c++; + temp1=0;temp2=0; + while (*c) + {temp1+=text_width(*c++)+10;temp2++;} + if (temp1>winx-2*MSG_L_MARGIN) winx=temp1+2*MSG_L_MARGIN; + txt_max=winx-MSG_A_MARGIN; + txt_h=0; + while (*text) + { + memset(buf,0,sizeof(buf)); + p=buf; + while (text_width(buf)txt_max) while (*(--p)!=' ') text--; + if (*text=='\n') text++; + *p='\0'; + txt_h=text_height(buf); + define(-1,MSG_L_MARGIN,winy,txt_max,txt_h,0,label,&buf); + property(NULL,NULL,flat_color(MSG_F_COLOR),MSG_COLOR); + o_end->f_color[0]=0; + winy+=txt_h; + } + winy+=40; + xp=(SCR_WIDTH_X>>1)-(winx>>1); + yp=(SCR_WIDTH_Y>>1)-(winy>>1); + waktual->x=xp;waktual->y=yp;waktual->xs=winx;waktual->ys=winy; + define(0,1,1,winx-2,text_height(title)+2,0,win_label,title); + ctl=def_border(5,MSG_COLOR); + property(ctl,NULL,flat_color(MSG_F_COLOR),0x10); + ctl=def_border(1,0); + c=&text;c++; + for (i=1;i<=temp2;i++) + { + int sz; + + sz=(winx/(temp2+1))>>1; + if (sz>1),10,sz+5,20,3,button,*c); + property(ctl,NULL,flat_color(0),RGB555(24,24,24));on_change(terminate); + c++; + } + set_window_modal(); + redraw_window(); + escape(); + temp2=o_aktual->id; + close_window(waktual); + return temp2; + } + + +//------------------------------------------------------------- + + +void resizer_draw(int x1,int y1,int x2,int y2,OBJREC *o) + { + CTL3D ctl; + + highlight(&ctl,o->color); + curcolor=o->color; + bar(x1,y1,x2,y2); + curcolor=ctl.light; + line(x2-1,y1+1,x1+1,y2-1); + line(x2-1,(y1+y2)>>1,(x1+x2)>>1,y2-1); + curcolor=ctl.shadow; + line(x2-1,y1+4,x1+4,y2-1); + line(x2-1,y1+2,x2-1,y1+4); + line(x1+2,y2-1,x1+4,y2-1); + line(x2-1,((y1+y2)>>1)+4,((x1+x2)>>1)+4,y2-1); + line(x2-1,((y1+y2)>>1)+2,x2-1,((y1+y2)>>1)+4); + line(((x1+x2)>>1)+2,y2-1,((x1+x2)>>1)+4,y2-1); + } + +void resizer_event(EVENT_MSG *msg,OBJREC *o) + { + MS_EVENT *ms; + static char run=0; + static word xref,yref; + static WINDOW w; + static moved=0; + static drawed=0; + + o; + if (msg->msg==E_INIT) return; + if (msg->msg==E_TIMER && !drawed) + if (!moved) + { + drawed=1; + redraw_desktop(); + moved=0; + } + else + { + drawed=0; + moved=0; + } + if (msg->msg==E_MOUSE) + { + ms=get_mouse(msg); + if (run) + { + char force_redraw=0; + int new; + //xor_rectangle(w.x,w.y,w.xs,w.ys); + if (ms->event_type & 4) + { + run=0; + redraw_desktop(); + send_message(E_DONE,E_MOUSE,resizer_event); + msg->msg=-1; + return; + } + new=ms->x-waktual->x+xref;if (newy-waktual->y+yref;if (newevent_type & 2) + { + run=1; + memcpy(&w,waktual,sizeof(WINDOW)); + //xor_rectangle(w.x,w.y,w.xs,w.ys); + xref=waktual->xs-(ms->x-waktual->x); + yref=waktual->ys-(ms->y-waktual->y); + send_message(E_ADD,E_MOUSE,resizer_event); + freeze_on_exit=1; + } + } + if (msg->msg==E_LOST_FOCUS && run) + { + run=0; + redraw_desktop(); + send_message(E_DONE,E_MOUSE,resizer_event); + msg->msg=-1; + return; + } +if (msg->msg!=E_TIMER) msg->msg=-1; + return; + } + + + +void resizer(OBJREC *o) + { + //o->runs[0]=resizer_init; + o->runs[1]=resizer_draw; + o->runs[2]=resizer_event; + } diff --git a/LIBS/BASICOBJ.H b/LIBS/BASICOBJ.H new file mode 100644 index 0000000..fde90ee --- /dev/null +++ b/LIBS/BASICOBJ.H @@ -0,0 +1,38 @@ +#define MEMTEXT "Pamt: " + +#define E_STATUS_LINE 60 + +extern word *msg_box_font; +extern word *msg_icn_font; + +int msg_box(char *title, char icone, char *text, ... ); + + +void highlight(CTL3D *c,word color); +CTL3D *def_border(int btype,int color); +void xor_rectangle(int x,int y,int xs,int ys); + +// status lines +void status_line(EVENT_MSG *msg,T_EVENT_ROOT **user_data); +void *status_mem_info(EVENT_MSG *msg); +void *mouse_xy(EVENT_MSG *msg); +void *show_time(EVENT_MSG *msg); + +// objects +//void sample(OBJREC *o); +void button(OBJREC *o); +void win_label(OBJREC *o); +void check_box(OBJREC *o); +void radio_butts(OBJREC *o); +void toggle_button(OBJREC *o); +void input_line(OBJREC *o); +void label(OBJREC *o); +void mid_label(OBJREC *o); +void scroll_bar_v(OBJREC *o); +void scroll_button(OBJREC *o); +void scroll_support(); +void scroll_bar_h(OBJREC *o); +void button2(OBJREC *o); +void resizer(OBJREC *o); + + diff --git a/LIBS/BGRAPH.C b/LIBS/BGRAPH.C new file mode 100644 index 0000000..c4a74b2 --- /dev/null +++ b/LIBS/BGRAPH.C @@ -0,0 +1,261 @@ +#include "types.h" +//#include +#include +#include +#include +#include +#include +#include +#include "bgraph.h" + +word *lbuffer; +word *screen; +word curcolor,charcolors[7] = {0x0000,0x03E0,0x0380,0x0300,0x0280,0x0000,0x0000}; +longint linelen; +word *curfont,*writepos,writeposx; +byte fontdsize=0; +byte *palmem,*xlatmem; +void (*showview)(word,word,word,word); +char line480=0; +long screen_buffer_size=512000; + +void *mscursor,*mssavebuffer=NULL; +integer mscuroldx=0,mscuroldy=0; +integer msshowx=0,msshowy=0; +long pictlen; // Tato promenna je pouze pouzita v BGRAPH1.ASM + +void line32(word x1,word y1, word x2, word y2) + { + line_32(x1,y1,(x2-x1),(y2-y1)); + } + +void position(word x,word y) + { + writeposx=x; + writepos=getadr32(x,y); + } + +void outtext(char *text) + { + byte pos; + + if (fontdsize) + while (*text) + { + char2_32(writepos,curfont,*text); + pos=(charsize(curfont,*text) & 0xff)<<1; + writepos+=pos; + writeposx+=pos;text++; + } + else + while (*text) + { + char_32(writepos,curfont,*text); + pos=charsize(curfont,*text) & 0xff; + writepos+=pos; + writeposx+=pos;text++; + } + } + + + + +int initmode32() + { + MODEinfo data; + + getmodeinfo(&data,0x11e-line480*0xe); + if (!(data.modeattr & MA_SUPP)) return -1; + if (!(data.modeattr & MA_LINEARFBUF)) return -2; + setvesamode(0x411e-line480*0xe,-1); + lbuffer=(word *)physicalalloc((long)data.linearbuffer,screen_buffer_size); + screen=lbuffer; + linelen=640*2; + showview=showview32; + screen=(void *)malloc(screen_buffer_size); + return 0; + } +int initmode256(void *paletefile) + { + MODEinfo data; + + getmodeinfo(&data,0x100+line480); + if (!(data.modeattr & MA_SUPP)) return -1; + if (!(data.modeattr & MA_LINEARFBUF)) return -2; + setvesamode(0x4100+line480,-1); + lbuffer=(word *)physicalalloc((long)data.linearbuffer,screen_buffer_size>>1); + screen=lbuffer; + linelen=640*2; + palmem=(char *)paletefile; + xlatmem=palmem+768; + setpal((void *)palmem); + showview=showview256; + screen=(void *)malloc(screen_buffer_size); + return 0; + } + + +int initmode_lo(void *paletefile) + { + _setvideomode(_MRES256COLOR); + palmem=(char *)paletefile; + xlatmem=palmem+768; + setpal((void *)palmem); + linelen=640*2; + lbuffer=(void *)0xa0000; + showview=showview_lo; + screen=(void *)malloc(512000); + return 0; + } + +void closemode() + { + free(screen); + _setvideomode(0x3); + } + +void showview32(word x,word y,word xs,word ys) + { + register longint a; + + if (x>640 || y>400) return; + if (xs==0) xs=640; + if (ys==0) ys=400; + if (x+xs>640) xs=640-x; + if (y+ys>400) ys=400-y; + if (xs>500 && ys>320) + { + redraw32(screen,lbuffer,NULL); + return; + } + a=(x<<1)+linelen*y; + redrawbox32(xs,ys,(void *)((char *)screen+a),(void *)((char *)lbuffer+a)); + } + +void showview256(word x,word y,word xs,word ys) + { + register longint a; + + if (xs==0) xs=640; + if (ys==0) ys=400; + x&=0xfffe;y&=0xfffe;xs+=2;ys+=2; + if (x>640 || y>400) return; + if (x+xs>640) xs=640-x; + if (y+ys>400) ys=400-y; + if (xs>500 && ys>320) + { + redraw256(screen,lbuffer,xlatmem); + return; + } + a=(x<<1)+linelen*y; + redrawbox256(xs,ys,(void *)((char *)screen+a),(void *)((char *)lbuffer+(a>>1)),xlatmem); + } + +void showview_lo(word x,word y,word xs,word ys) + { + register longint a,b; + + if (xs==0) xs=640; + if (ys==0) ys=400; + x&=0xfffe;y&=0xfffe;xs+=2;ys+=2; + if (ys==0) ys=400; + if (x+xs>640) xs=640-x; + if (y+ys>400) ys=400-y; + if (xs>500 && ys>320) + { + redraw_lo(screen,lbuffer,xlatmem); + return; + } + a=(x<<1)+linelen*y; + b=(x>>1)+320*(y>>1); + redrawbox_lo(xs,ys,(void *)((char *)screen+a),(void *)((char *)lbuffer+b),xlatmem); + } + + + + +void show_ms_cursor(char copy,integer x, integer y) + { + integer xs,ys; + + xs=*(integer *)mscursor; + ys=*((integer *)mscursor+1); + get_picture(x,y,xs,ys,mssavebuffer); + put_picture(x,y,mscursor); + if (copy) + { + mscuroldx=x; + mscuroldy=y; + } + } + +void hide_ms_cursor() + { + put_picture(mscuroldx,mscuroldy,mssavebuffer); + } + +void *register_ms_cursor(void *cursor) + { + integer xs,ys; + + mscursor=cursor; + xs=*(integer *)mscursor; + ys=*((integer *)mscursor+1); + if (mssavebuffer!=NULL) free(mssavebuffer); + mssavebuffer=malloc(xs*ys*2+10);//5 bajtu pro strejcka prihodu + return mssavebuffer; + } + +void move_ms_cursor(integer newx,integer newy) + { + integer xs,ys; + + if (newx<0) newx=0; + if (newy<0) newy=0; + if (newx>639) newx=639; + if (newy>399) newy=399; + xs=*(integer *)mscursor; + ys=*((integer *)mscursor+1); + put_picture(mscuroldx,mscuroldy,mssavebuffer); + show_ms_cursor(0,newx,newy); + showview(msshowx,msshowy,xs,ys); + mscuroldx=newx;mscuroldy=newy; + msshowx=newx;msshowy=newy; + showview(msshowx,msshowy,xs,ys); + } + +int text_height(char *text) + { + char max=0,cur; + + while (*text) + if ((cur=charsize(curfont,*text++)>>8)>max) max=cur; + return max<>1;break; + case 2:x-=text_width(text);break; + } + switch (aligny) + { + case 1:y-=text_height(text)>>1;break; + case 2:y-=text_height(text);break; + } + position(x,y); + } + + diff --git a/LIBS/BGRAPH.H b/LIBS/BGRAPH.H new file mode 100644 index 0000000..d1e8021 --- /dev/null +++ b/LIBS/BGRAPH.H @@ -0,0 +1,155 @@ +#include "types.h" +#define line line32 +#define hor_line hor_line32 +#define ver_line ver_line32 +#define bar bar32 +#define point point32 + +word *GetScreenAdr(); +word *GetBuffer2nd(); +void RedirectScreen(word *newaddr); +void RestoreScreen(); +void RedirectScreenBufferSecond(); + + +extern word curcolor,charcolors[7]; +extern long scr_linelen; +extern long scr_linelen2; +extern long dx_linelen; +extern word *curfont,*writepos,writeposx; +extern byte fontdsize; +extern byte *palmem,*xlatmem; +extern void (*showview)(word,word,word,word); +extern char line480; +extern long screen_buffer_size; +extern char banking; +extern char __skip_change_line_test; +extern char no_restore_mode; + +static __inline word *getadr32(longint x,longint y) + { + return GetScreenAdr()+scr_linelen2*y+x; + } + +static __inline void point32(longint x,longint y, word color) + { + *getadr32(x,y)=color; + } +void bar32(int x1,int y1, int x2, int y2); +//#pragma aux bar32 parm [eAX] [eBX] [eCX] [eDX] modify [ESI EDI]; +void hor_line32(int x1,int y1,int x2); +//#pragma aux hor_line32 parm [eSi] [eAX] [eCX] modify [eDI eDX]; +void ver_line32(int x1,int y1,int y2); +//#pragma aux ver_line32 parm [eSi] [eAX] [eCX] modify [eDX]; +void hor_line_xor(int x1,int y1,int x2); +//#pragma aux hor_line_xor parm [eSi] [eAX] [eCX] modify [eDI eDX]; +void ver_line_xor(int x1,int y1,int y2); +//#pragma aux ver_line_xor parm [eSi] [eAX] [eCX] modify [eDX]; +void line_32(int x,int y,int xs,int ys); +//#pragma aux line_32 parm [esi] [eax] [ecx] [ebx] modify [edx edi] +void char_32(word *posit,word *font,char znak); +//#pragma aux char_32 parm [edi] [esi] [eax] modify [eax ebx ecx edx] +void char2_32(word *posit,word *font,char znak); +//#pragma aux char2_32 parm [edi] [esi] [eax] modify [eax ebx ecx edx] +word charsize(word *font,char znak); +//#pragma aux charsize parm [esi] [eax] +void put_picture(word x,word y,void *p); +//#pragma aux put_picture parm [esi] [eax] [edi] modify [ebx ecx edx] +void get_picture(word x,word y,word xs,word ys,void *p); +//#pragma aux get_picture parm [esi] [eax] [ebx] [ecx] [edi] modify [edx] +void setpal(void *paleta); +//#pragma aux setpal parm [esi] modify [eax edx] +void redraw_lo(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw_lo parm [esi][edi][ebx] modify[eax ecx edx] +void redraw256(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw256 parm [esi][edi][ebx] modify [eax ecx edx] +void redraw256b(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw256b parm [esi][edi][ebx] modify [eax ecx edx] +void redraw32(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw32 parm [esi][edi][ebx] modify [ecx] +void redraw32b(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw32b parm [esi][edi][ebx] modify [ecx eax] +void redraw64(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw64 parm [esi][edi][ebx] modify [ecx eax] +void redraw64b(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw64b parm [esi][edi][ebx] modify [ecx eax] +void redraw32bb(void *screen,void *lbuffer,byte *xlat); +//#pragma aux redraw32bb parm [esi][edi][ebx] modify [ecx eax] +void redrawbox_lo(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox_lo parm [ecx][edx][esi][edi][ebx] modify [eax edx] +void redrawbox256(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox256 parm [edx][ecx][esi][edi][ebx] modify [eax edx] +void redrawbox256b(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox256b parm [edx][ecx][esi][edi][ebx] modify [eax edx] +void redrawbox32(word xs,word ys,void *screen,void *lbuffer); +//#pragma aux redrawbox32 parm [ebx][edx][esi][edi] modify [ecx eax] +void redrawbox32b(word xs,word ys,void *screen,void *lbuffer); +//#pragma aux redrawbox32b parm [ebx][edx][esi][edi] modify [ecx eax] +void redrawbox64(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox64 parm [ecx][edx][esi][edi][ebx] modify [eax] +void redrawbox64b(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox64b parm [ecx][edx][esi][edi][ebx]modify [eax] +void redrawbox32bb(word xs,word ys,void *screen,void *lbuffer); +//#pragma aux redrawbox32bb parm [ebx][edx][esi][edi] modify [ecx] +void redraw16(void *screen,void *lbuffer,byte *xlat); +void redrawbox16(word xs,word ys,void *screen,void *lbuffer,byte *xlat); +//#pragma aux redrawbox16 parm [edx][ecx][esi][edi][ebx] modify [eax edx] +//#pragma aux redraw16 parm [esi][edi][ebx] modify [ecx] +void showview32(word x,word y,word xs,word ys); +void showview256(word x,word y,word xs,word ys); +void showview_lo(word x,word y,word xs,word ys); +void outtext(char *text); +int initmode_dx(char inwindow, char zoom, char monitor, int refresh); +int initmode32(); +int initmode32b(); +int initmode256(void *paletefile); +int initmode256b(void *paletefile); +int initmode_lo(void *paletefile); +int initmode16(void *paletefile); +int initmode64(void *paletefile); +int initmode64b(void *paletefile); +void *create_hixlat(); +void closemode(); +void line32(word x1,word y1, word x2, word y2); +void position(word x,word y); +void outtext(char *text); +void show_ms_cursor(integer x,integer y); +void *register_ms_cursor(void *cursor); +void move_ms_cursor(integer newx,integer newy,char nodraw); +void hide_ms_cursor(); +int text_height(char *text); +int text_width(char *text); +void set_aligned_position(int x,int y,char alignx, char aligny,char *text); +void wait_retrace(); +void pal_optimize(); +void rectangle(int x1,int y1,int x2,int y2,int color); +word *mapvesaadr1(word *a); +void *create_special_palette(); +void *create_special_palette2(); +void *create_blw_palette16(); +void rel_position_x(word x); +int init_empty_mode(); + +void put_8bit_clipped(void *src,void *trg,int startline,int velx,int vely); +//#pragma aux put_8bit_clipped parm [ESI][EDI][EAX][EBX][EDX] modify [ECX]; +void put_textured_bar_(void *src,void *trg,int xsiz,int ysiz,int xofs,int yofs); +//#pragma aux put_textured_bar_ parm [EBX][EDI][EDX][ECX][ESI][EAX]; +void put_textured_bar(void *src,int x,int y,int xs,int ys,int xofs,int yofs); +void trans_bar(int x,int y,int xs,int ys,int barva); +//#pragma aux trans_bar parm [EDI][ESI][EDX][ECX][EBX] modify [EAX]; +void trans_bar25(int x,int y,int xs,int ys); +//#pragma aux trans_bar25 parm [EDI][ESI][EDX][ECX] modify [EAX EBX]; +void trans_line_x(int x,int y,int xs,int barva); +//#pragma aux trans_line_x parm [EDI][ESI][ECX][EDX] modify [EAX]; +void trans_line_y(int x,int y,int ys,int barva); +//#pragma aux trans_line_y parm [EDI][ESI][ECX][EDX] modify [EAX]; +void draw_placed_texture(short *txtr,int celx,int cely,int posx,int posy,int posz,char turn); + +void put_image(word *image,word *target,int start_line,int sizex,int sizey); +//#pragma aux put_image parm [ESI][EDI][EAX][EBX][EDX] modify [ECX] +void put_picture2picture(word *source,word *target,int xp,int yp); +//#pragma aux put_picture2picture parm [ESI][EDI][EAX][EDX] modify [ECX] + + + +#define swap_int(a,b) do {int c=a;a=b;b=c;} while (0); diff --git a/LIBS/BGRAPH1.ASM b/LIBS/BGRAPH1.ASM new file mode 100644 index 0000000..f779849 --- /dev/null +++ b/LIBS/BGRAPH1.ASM @@ -0,0 +1,658 @@ +.model small +.386 + + +DGROUP group _DATA +extrn _linelen:dword +extrn _screen:dword +extrn _curcolor:word +extrn _charcolors:word[7] +extrn _pictlen:dword +extrn _screen_buffer_size:dword + +SEGA000 equ 0a0000h + +_TEXT segment byte public 'CODE' use32 + assume CS:_TEXT + assume DS:DGROUP + + public getadr32_ +getadr32_: +getadr_:mul _linelen ;EAX - y; ESI - X; + shl esi,1 + add eax,esi + add eax,_screen + ret + + + public point32_ ;EAX - Y; ESI - X; ECX - COLOR +point32_: call getadr_ + mov [eax],cx + ret + + + + public bar32_ ;AX - X1, BX - Y1, CX - X2, DX - Y2 +bar32_: cmp cx,ax ;x1x1 + jnc horlin1 + xchg ecx,esi ;jestli ne tak je prohod +horlin1:sub ecx,esi ;xs=x2-x1+1 + inc ecx ; + mov si,ds ;ds -> es + mov es,si + mov edi,eax ;esi je adresa + mov ax,_curcolor ;nacti barvu + shl eax,16 + mov ax,_curcolor + shr ecx,1 + rep stosd ;nakresli caru + rcl ecx,1 + rep stosw ;popripade jeste jeden bod + pop es ;obnov es + ret + +public ver_line32_ +ver_line32_: ;EAX - Y1 ESI - X ECX - Y2 + cmp ecx,eax ;y2>y1 + jnc verlin1 + xchg ecx,eax ;jestli ne tak je prohod +verlin1:sub ecx,eax + inc ecx + call getadr_ ;eax obsahuje adresu bodu + mov esi,eax + mov ax,_curcolor ;nacti barvu +verlin2:mov [esi],ax ;kresli caru po bodech + add esi,_linelen + dec ecx + jnz verlin2 + ret + + public line_32_ +line_32_: ;eax - Y, esi - X, ecx - xs, ebx - ys (xs,ys muze byt zaporne) + or ecx,ecx + jns line1 ;kdyz je ecx (xs) zaporny je nutne otocit smer a presunout se na druhy konec linky + add esi,ecx + add eax,ebx + neg ebx + neg ecx +line1: push es ;uchovej es + or ecx,ecx ;kdyz je ecx=0 pak je to specialni pripad + inc ecx + jz lnext + call getadr_ ;zjisti adresu prvnihi bodu + mov edi,eax ;vloz ji do di + mov ax,ds ;ds -> es + mov es,ax + mov ax,_curcolor ;nacti aktualni barvu + or ebx,ebx ;kontrola zda je ebx>=0 + js lineup ;neni pak bude se kreslit nahoru + xor esi,esi ;vynuluj esi - pocitadlo mezikroku + mov edx,ecx ;delku cary na ose x do porovnavaciho registru + inc ebx +lined3: add esi,ebx ;do mezikroku pricti ys + cmp esi,edx ;kdyz to prekrocilo poronavaci registr + jc lined1 ;zacnes kreslit dolu, jinak v pravo +lined2: mov [edi],ax;zapis bod + add edi,_linelen ;a posun dolu + sub esi,edx ;odect od mezikroku hodnotu v porovnavacim registru + cmp esi,edx ;je stale preteceni? + jnc lined2 ;pokud ano opakuj zapsani bodu + add edi,2 ;dalsi xs + dec ecx ;sniz citac Xs + jnz lined3 ;pokracuj pro dalsi Xs + jmp linee ;pokud to byl posledni, pak konec +lined1: stosw ;zapis bod a posun v pravo + dec ecx ;pokracuj pro dalsi ys + jnz lined3 ;dokud neni konec + jmp linee ;pak jdi na lineEnd +lineup: neg ebx ;neguj ebx + xor esi,esi ;vynuluj esi - pocitadlo mezikroku + mov edx,ecx ;delku cary na ose x do porovnavaciho registru + inc ebx +lineu3: add esi,ebx ;do mezikroku pricti ys + cmp esi,edx ;kdyz to prekrocilo poronavaci registr + jc lineu1 ;zacnes kreslit nahoru, jinak v pravo +lineu2: mov [edi],ax;zapis bod + sub edi,_linelen ;a posun nahoru + sub esi,edx ;odect od mezikroku hodnotu v porovnavacim registru + cmp esi,edx ;je stale preteceni? + jnc lineu2 ;pokud ano opakuj zapsani bodu + add edi,2 ;dalsi xs + dec ecx ;sniz citac Xs + jnz lineu3 ;pokracuj pro dalsi Xs + jmp linee ;pokud to byl posledni, pak konec +lineu1: stosw ;zapis bod a posun v pravo + dec ecx ;pokracuj pro dalsi ys + jnz lineu3 ;dokud neni konec + jmp linee +lnext: mov ecx,ebx + add ecx,eax + call ver_line32_ +linee: pop es + ret + + public char_32_ +char_32_: ;edi - pozice na obrazovce + ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chrend + add esi,eax + lodsw + xor dl,dl ;dl - je citac transparetnich pozic + mov cx,ax ;cl - XRES, ch - YRES +chr6: mov ebx,edi ;ebx - ukazuje po radcich v jednom sloupci + mov dh,ch ;dh - bude citac radku +chr5: or dl,dl ;pokud je dl = 0 pak se cte dalsi bajt + jnz chr1 ;jinak je dalsi bod jenom transparetni + lodsb ;cti barvu + or al,al ;pokud je 0 pak je transparetni + jz chr2 ;preskoc kresleni + cmp al,8 ;8 a vice jsou informace o opakovanych transparetnich bodech + jnc chr3 ;(viz FONTEDIT.DOC). Pak se podle toho zarid + and eax,0ffh;v eax jen dolnich 8 bitu + dec al + mov ax,_charcolors[EAX*2] ;vyjmi barvu + cmp ax,0ffffh;0xffff je barva ktera se nekresli; + jz chr4 ; + mov [ebx],ax;zobraz ji na obrazovce + jmp chr4 ;a skoc na konec smycky +chr3: cmp al,0ffh ;pokud je al=255 pak jsme narazily na terminator. + jz chrend ;V tom pripade KONEC + sub al,6 ;odecti do al 6. Ziskas pocet transparetnich pozic + mov dl,al ;uloz je do citace +chr1: dec dl ;pro kazdou pozici to dl odecti dokud neni 0 +chr2: +chr4: add ebx,_linelen;dalsi radka + dec dh ;odecti citac radek + jnz chr5 ;dokud neni nula + add edi,2 ;dalsi sloupec + dec cl ;odecti citac sloupcu + jnz chr6 ;dokud neni nula +chrend: ret ;konec + + public char2_32_ +char2_32_: ;edi - pozice na obrazovce + ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chr2end + add esi,eax + lodsw + xor dl,dl ;dl - je citac transparetnich pozic + mov cx,ax ;cl - XRES, ch - YRES +chr26: mov ebx,edi ;ebx - ukazuje po radcich v jednom sloupci + mov dh,ch ;dh - bude citac radku +chr25: or dl,dl ;pokud je dl = 0 pak se cte dalsi bajt + jnz chr21 ;jinak je dalsi bod jenom transparetni + lodsb ;cti barvu + or al,al ;pokud je 0 pak je transparetni + jz chr22 ;preskoc kresleni + cmp al,8 ;8 a vice jsou informace o opakovanych transparetnich bodech + jnc chr23 ;(viz FONTEDIT.DOC). Pak se podle toho zarid + and eax,0ffh;v eax jen dolnich 8 bitu + dec al + mov ax,_charcolors[EAX*2] ;vyjmi barvu + push ebx + mov [ebx],ax;zobraz ji na obrazovce + mov [ebx+2],ax;zobraz ji na obrazovce + add ebx,_linelen + mov [ebx],ax;zobraz ji na obrazovce + mov [ebx+2],ax;zobraz ji na obrazovce + pop ebx + jmp chr24 ;a skoc na konec smycky +chr23: cmp al,0ffh ;pokud je al=255 pak jsme narazily na terminator. + jz chr2end ;V tom pripade KONEC + sub al,6 ;odecti do al 6. Ziskas pocet transparetnich pozic + mov dl,al ;uloz je do citace +chr21: dec dl ;pro kazdou pozici to dl odecti dokud neni 0 +chr22: +chr24: add ebx,_linelen;dalsi radka + add ebx,_linelen + dec dh ;odecti citac radek + jnz chr25 ;dokud neni nula + add edi,4 ;dalsi sloupec + dec cl ;odecti citac sloupcu + jnz chr26 ;dokud neni nula +chr2end: ret ;konec + + public charsize_ +charsize_: ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chsend + add esi,eax + lodsw +chsend: and eax,0ffffh + ret + + public put_picture_ +put_picture_: ;esi - X + ;eax - Y + ;edi - obrazek + mov ecx,esi ;uchovej x v ecx + mov ebx,eax ;uchovej y v ebx + call getadr_ ;zjisti adresu bodu + mov esi,eax ;vloz ji do esi + xchg esi,edi ;prohod esi a edi aby obsahovali zpravne informace + xor eax,eax ;vynuluj pripadne bajty v horni polovine eax + lodsw ;nacti xs + mov _pictlen,eax + mov edx,eax ;z kopiruj jeste do pracovniho dx + add edx,ecx ;pricti k nemu souradnici + cmp edx,640 ;je-li vetsi nez max velikost obrazovky x + jc ppok1 ; + mov eax,640 ;pak za eax dosad plnou velikost + sub eax,ecx ;odecti souradnici +ppok1: mov ecx,eax ;vloz do ecx + lodsw ;totez pro y + mov edx,eax + add edx,ebx + cmp edx,400 + jc ppok2 + mov eax,400 + sub eax,ebx +ppok2: mov edx,eax + lodsw + mov ebx,edi + cmp al,15 + jnz pp_next + jmp pp15bit +pp_next:cmp al,8 + jnz pp_nxt2 + jmp pp8bit +pp_nxt2:ret + +pp15bit:mov eax,ecx +pp15bi1:shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,_pictlen + sub ecx,eax + shl ecx,1 + add esi,ecx + mov ecx,eax + add ebx,_linelen + mov edi,ebx + dec edx + jnz pp15bi1 + ret + +pp8bit: push ebp + mov ebp,ecx + mov ebx,esi + add esi,512 +pp8bit1:xor eax,eax + lodsb + or al,al + jz pp8bit2 + mov eax,[ebx+eax*2] + stosw +pp8bit4:dec ecx + jnz pp8bit1 + mov ecx,ebp + sub edi,ecx + sub edi,ecx + add edi,_linelen + sub esi,ebp + add esi,_pictlen + dec edx + jnz pp8bit1 + pop ebp + ret +pp8bit2:add edi,2 + jmp pp8bit4 + + public setPal_ +setPal_:mov edx,3c6h + mov al,255 + out dx,al + xor ah,ah +setpal1:mov edx,3c8h + mov al,ah + out dx,al + mov edx,3c9h + lodsb + out dx,al + lodsb + out dx,al + lodsb + out dx,al + inc ah + jne setPal1 + ret + + + public Redraw_lo_ +Redraw_lo_: ;esi 512Kb obrazovka + ;edi lbuffer + ;ebx xlattable + test ebx,1 + jz rdrwlo3 + inc ebx +rdrwlo3:push ebp + mov ebp,200 shl 16 + xor eax,eax + xor ecx,ecx + xor edx,edx +rdrwlo2:mov bp,160 +rdrwlo1:mov ecx,[esi] + mov edx,[esi+1280] + and ecx,7bdf7bdfh + and edx,7bdf7bdfh + add ecx,edx + shr ecx,1 + shrd ecx,edx,16 + and edx,7bdfh + and ecx,7bdfh + add edx,ecx + shr edx,1 + mov al,[ebx+edx*2] + xor ebx,1 + add esi,4 + mov ecx,[esi] + mov edx,[esi+1280] + and ecx,7bdf7bdfh + and edx,7bdf7bdfh + add ecx,edx + shr ecx,1 + shrd ecx,edx,16 + and edx,7bdfh + and ecx,7bdfh + add edx,ecx + shr edx,1 + mov ah,[ebx+edx*2] + stosw + xor ebx,1 + add esi,4 + dec bp + jnz rdrwlo1 + xor ebx,1 + add esi,1280 + sub ebp,65536 + jnz rdrwlo2 + pop ebp + ret + + public Redraw256_ +Redraw256_: ;esi - source + ;edi - target + ;ebx - xlat + + test ebx,1 + jz rdrwlo7 + inc ebx +rdrwlo7:xor eax,eax +rdrwlo4:mov ecx,400*65536 +rdrwlo6:mov cx,320 +rdrwlo5:mov edx,[esi] + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + shr edx,16 + xor ebx,1 + mov ah,[ebx+edx*2] + stosw + xor ebx,1 + dec cx + jnz rdrwlo5 + xor ebx,1 + sub ecx,65536 + jnz rdrwlo6 + ret + + public redraw32_ +redraw32_: ;esi source + ;edi target + ;ebx notused (xlat) + mov ecx,128000 + rep movsd + ret + + + public redrawbox_lo_ +redrawbox_lo_: ;esi source + ;edi target + ;ebx xlat + ;ecx xs + ;edx,ys + shr ecx,1 + shr edx,1 + dec edx + test ebx,1 + jz rboxlo3 + inc ebx +rboxlo3:push ebp + mov ebp,edx + shl ebp,16 + mov bp,cx + xor eax,eax + xor ecx,ecx + xor edx,edx +rboxlo2:push ebp + push esi + push edi +rboxlo1:mov ecx,[esi] + mov edx,[esi+1280] + and ecx,7bdf7bdfh + and edx,7bdf7bdfh + add ecx,edx + shr ecx,1 + shrd ecx,edx,16 + and edx,7bdfh + and ecx,7bdfh + add edx,ecx + shr edx,1 + mov al,[ebx+edx*2] + stosb + xor ebx,1 + add esi,4 + dec bp + jnz rboxlo1 + pop edi + pop esi + pop ebp + xor ebx,1 + add esi,_linelen + add esi,_linelen + add edi,320 + sub ebp,65536 + jnc rboxlo2 + pop ebp + ret + + public Redrawbox256_ +Redrawbox256_: ;esi - source + ;edi - target + ;ebx - xlat + ;ecx - ys + ;edx - xs + + shl ecx,16 + shr edx,1 + mov cx,dx + test ebx,1 + jz rboxlo7 + inc ebx +rboxlo7:xor eax,eax +rboxlo6:push ecx + push esi + push edi +rboxlo5:mov edx,[esi] + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + shr edx,16 + xor ebx,1 + mov ah,[ebx+edx*2] + stosw + xor ebx,1 + dec cx + jnz rboxlo5 + pop edi + pop esi + pop ecx + add esi,_linelen + add edi,640 + xor ebx,1 + sub ecx,65536 + test ecx,0ffff0000h + jnz rboxlo6 + ret + + public redrawbox32_ +redrawbox32_: ;esi source + ;edi target + ;ebx xs + ;edx ys + shr ebx,1 +rbox32: mov ecx,ebx + rep movsd + mov ecx,ebx + shl ecx,2 + sub esi,ecx + sub edi,ecx + add esi,_linelen + add edi,_linelen + dec edx + jnz rbox32 + ret + + public get_picture_ +get_picture_: ;esi - X + ;eax - Y + ;ebx - xs + ;ecx - ys + ;edi - obrazek + mov [edi],ebx ;zapis velikost obrazku + mov [edi+2],ecx + mov ecx,esi ;uchovej x v ecx + mov ebx,eax ;uchovej y v ebx + call getadr_ ;zjisti adresu bodu + mov esi,eax ;vloz ji do esi + xor eax,eax ;vynuluj pripadne bajty v horni polovine eax + mov ax,[edi];vem velikost x + add edi,2 + mov _pictlen,eax + mov edx,eax ;z kopiruj jeste do pracovniho dx + add edx,ecx ;pricti k nemu souradnici + cmp edx,640 ;je-li vetsi nez max velikost obrazovky x + jc gpok1 ; + mov eax,640 ;pak za eax dosad plnou velikost + sub eax,ecx ;odecti souradnici +gpok1: mov ecx,eax ;vloz do ecx + mov ax,[edi];vem velikost y + add edi,2 + mov edx,eax + add edx,ebx + cmp edx,400 + jc gpok2 + mov eax,400 + sub eax,ebx +gpok2: mov edx,eax + mov ax,15 ;nastav typ 15 + stosw ;zapis + mov ebx,esi ;uloz esi jeste do ebx +gp15bit:mov eax,ecx ;uloz ecx jeste do eax +gp15bi1:shr ecx,1 ;pocet dvojic bodu + rep movsd ;presun do pameti + rcl ecx,1 ;pokud zbyl jeste jeden + rep movsw ;tak ted + mov ecx,_pictlen + sub ecx,eax + shl ecx,1 + add edi,ecx ;jdi na dalsi radku v obrazku + mov ecx,eax ;obnov counter + add ebx,_linelen ;jdi na dalsi radku na obrazovce + mov esi,ebx ;obnov esi + dec edx ;dokud neni konec + jnz gp15bi1 + ret + + public hor_line_xor_ +Hor_line_xor_: ;EAX - Y ESI - X1 ECX - X2 + call getadr_ ;eax obsahuje adresu bodu + shr esi,1 + cmp ecx,esi ;x2>x1 + jnc xhorlin1 + xchg ecx,esi ;jestli ne tak je prohod +xhorlin1:sub ecx,esi ;xs=x2-x1+1 + inc ecx ; + mov edi,eax ;esi je adresa + mov ax,_curcolor ;nacti barvu +xhorlin2:xor [edi],ax + add edi,2 + dec ecx + jnz xhorlin2 + ret + +public ver_line_xor_ +ver_line_xor_: ;EAX - Y1 ESI - X ECX - Y2 + cmp ecx,eax ;y2>y1 + jnc xverlin1 + xchg ecx,eax ;jestli ne tak je prohod +xverlin1:sub ecx,eax + inc ecx + call getadr_ ;eax obsahuje adresu bodu + mov esi,eax + mov ax,_curcolor ;nacti barvu +xverlin2:xor [esi],ax ;kresli caru po bodech + add esi,_linelen + dec ecx + jnz xverlin2 + ret + + +_TEXT ends + +END diff --git a/LIBS/BGRAPH2A.ASM b/LIBS/BGRAPH2A.ASM new file mode 100644 index 0000000..f548846 --- /dev/null +++ b/LIBS/BGRAPH2A.ASM @@ -0,0 +1,1132 @@ +.model small +.386 + + +DGROUP group _DATA +extrn _linelen:dword +extrn _screen:dword +extrn _curcolor:word +extrn _charcolors:word[7] +extrn _pictlen:dword +extrn _screen_buffer_size:dword +extrn _lastbank:dword +extrn _granuality:dword +extrn _gran_mask:dword + +SEGA000 equ 0a0000h + +_TEXT segment byte public 'CODE' use32 + assume CS:_TEXT + assume DS:DGROUP + +extrn switchvesabank_:proc + + + public getadr32_ +getadr32_: +getadr_:mul _linelen ;EAX - y; ESI - X; + shl esi,1 + add eax,esi + add eax,_screen + ret + + + public point32_ ;EAX - Y; ESI - X; ECX - COLOR +point32_: call getadr_ + mov [eax],cx + ret + + + + public bar32_ ;AX - X1, BX - Y1, CX - X2, DX - Y2 +bar32_: cmp cx,ax ;x1x1 + jnc horlin1 + xchg ecx,esi ;jestli ne tak je prohod +horlin1:sub ecx,esi ;xs=x2-x1+1 + inc ecx ; + mov si,ds ;ds -> es + mov es,si + mov edi,eax ;esi je adresa + mov ax,_curcolor ;nacti barvu + shl eax,16 + mov ax,_curcolor + shr ecx,1 + rep stosd ;nakresli caru + rcl ecx,1 + rep stosw ;popripade jeste jeden bod + pop es ;obnov es + ret + +public ver_line32_ +ver_line32_: ;EAX - Y1 ESI - X ECX - Y2 + cmp ecx,eax ;y2>y1 + jnc verlin1 + xchg ecx,eax ;jestli ne tak je prohod +verlin1:sub ecx,eax + inc ecx + call getadr_ ;eax obsahuje adresu bodu + mov esi,eax + mov ax,_curcolor ;nacti barvu +verlin2:mov [esi],ax ;kresli caru po bodech + add esi,_linelen + dec ecx + jnz verlin2 + ret + + public line_32_ +line_32_: ;eax - Y, esi - X, ecx - xs, ebx - ys (xs,ys muze byt zaporne) + or ecx,ecx + jns line1 ;kdyz je ecx (xs) zaporny je nutne otocit smer a presunout se na druhy konec linky + add esi,ecx + add eax,ebx + neg ebx + neg ecx +line1: push es ;uchovej es + or ecx,ecx ;kdyz je ecx=0 pak je to specialni pripad + inc ecx + jz lnext + call getadr_ ;zjisti adresu prvnihi bodu + mov edi,eax ;vloz ji do di + mov ax,_curcolor ;nacti aktualni barvu + or ebx,ebx ;kontrola zda je ebx>=0 + js lineup ;neni pak bude se kreslit nahoru + mov esi,edx ;vynuluj esi - pocitadlo mezikroku + shr esi,1 + mov edx,ecx ;delku cary na ose x do porovnavaciho registru + inc ebx +lined3: add esi,ebx ;do mezikroku pricti ys + cmp esi,edx ;kdyz to prekrocilo poronavaci registr + jc lined1 ;zacnes kreslit dolu, jinak v pravo +lined2: mov [edi],ax;zapis bod + add edi,_linelen ;a posun dolu + sub esi,edx ;odect od mezikroku hodnotu v porovnavacim registru + cmp esi,edx ;je stale preteceni? + jnc lined2 ;pokud ano opakuj zapsani bodu + add edi,2 ;dalsi xs + dec ecx ;sniz citac Xs + jnz lined3 ;pokracuj pro dalsi Xs + jmp linee ;pokud to byl posledni, pak konec +lined1: stosw ;zapis bod a posun v pravo + dec ecx ;pokracuj pro dalsi ys + jnz lined3 ;dokud neni konec + jmp linee ;pak jdi na lineEnd +lineup: neg ebx ;neguj ebx + mov esi,edx ;vynuluj esi - pocitadlo mezikroku + shr esi,1 + mov edx,ecx ;delku cary na ose x do porovnavaciho registru + inc ebx +lineu3: add esi,ebx ;do mezikroku pricti ys + cmp esi,edx ;kdyz to prekrocilo poronavaci registr + jc lineu1 ;zacnes kreslit nahoru, jinak v pravo +lineu2: mov [edi],ax;zapis bod + sub edi,_linelen ;a posun nahoru + sub esi,edx ;odect od mezikroku hodnotu v porovnavacim registru + cmp esi,edx ;je stale preteceni? + jnc lineu2 ;pokud ano opakuj zapsani bodu + add edi,2 ;dalsi xs + dec ecx ;sniz citac Xs + jnz lineu3 ;pokracuj pro dalsi Xs + jmp linee ;pokud to byl posledni, pak konec +lineu1: stosw ;zapis bod a posun v pravo + dec ecx ;pokracuj pro dalsi ys + jnz lineu3 ;dokud neni konec + jmp linee +lnext: mov ecx,ebx + add ecx,eax + call ver_line32_ +linee: pop es + ret + + public char_32_ +char_32_: ;edi - pozice na obrazovce + ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chrend + add esi,eax + lodsw + xor dl,dl ;dl - je citac transparetnich pozic + mov cx,ax ;cl - XRES, ch - YRES +chr6: mov ebx,edi ;ebx - ukazuje po radcich v jednom sloupci + mov dh,ch ;dh - bude citac radku +chr5: or dl,dl ;pokud je dl = 0 pak se cte dalsi bajt + jnz chr1 ;jinak je dalsi bod jenom transparetni + lodsb ;cti barvu + or al,al ;pokud je 0 pak je transparetni + jz chr2 ;preskoc kresleni + cmp al,8 ;8 a vice jsou informace o opakovanych transparetnich bodech + jnc chr3 ;(viz FONTEDIT.DOC). Pak se podle toho zarid + and eax,0ffh;v eax jen dolnich 8 bitu + dec al + mov ax,_charcolors[EAX*2] ;vyjmi barvu + cmp ax,0ffffh;0xffff je barva ktera se nekresli; + jz chr4 ; + mov [ebx],ax;zobraz ji na obrazovce + jmp chr4 ;a skoc na konec smycky +chr3: cmp al,0ffh ;pokud je al=255 pak jsme narazily na terminator. + jz chrend ;V tom pripade KONEC + sub al,6 ;odecti do al 6. Ziskas pocet transparetnich pozic + mov dl,al ;uloz je do citace +chr1: dec dl ;pro kazdou pozici to dl odecti dokud neni 0 +chr2: +chr4: add ebx,_linelen;dalsi radka + dec dh ;odecti citac radek + jnz chr5 ;dokud neni nula + add edi,2 ;dalsi sloupec + dec cl ;odecti citac sloupcu + jnz chr6 ;dokud neni nula +chrend: ret ;konec + + public char2_32_ +char2_32_: ;edi - pozice na obrazovce + ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chr2end + add esi,eax + lodsw + xor dl,dl ;dl - je citac transparetnich pozic + mov cx,ax ;cl - XRES, ch - YRES +chr26: mov ebx,edi ;ebx - ukazuje po radcich v jednom sloupci + mov dh,ch ;dh - bude citac radku +chr25: or dl,dl ;pokud je dl = 0 pak se cte dalsi bajt + jnz chr21 ;jinak je dalsi bod jenom transparetni + lodsb ;cti barvu + or al,al ;pokud je 0 pak je transparetni + jz chr22 ;preskoc kresleni + cmp al,8 ;8 a vice jsou informace o opakovanych transparetnich bodech + jnc chr23 ;(viz FONTEDIT.DOC). Pak se podle toho zarid + and eax,0ffh;v eax jen dolnich 8 bitu + dec al + mov ax,_charcolors[EAX*2] ;vyjmi barvu + push ebx + mov [ebx],ax;zobraz ji na obrazovce + mov [ebx+2],ax;zobraz ji na obrazovce + add ebx,_linelen + mov [ebx],ax;zobraz ji na obrazovce + mov [ebx+2],ax;zobraz ji na obrazovce + pop ebx + jmp chr24 ;a skoc na konec smycky +chr23: cmp al,0ffh ;pokud je al=255 pak jsme narazily na terminator. + jz chr2end ;V tom pripade KONEC + sub al,6 ;odecti do al 6. Ziskas pocet transparetnich pozic + mov dl,al ;uloz je do citace +chr21: dec dl ;pro kazdou pozici to dl odecti dokud neni 0 +chr22: +chr24: add ebx,_linelen;dalsi radka + add ebx,_linelen + dec dh ;odecti citac radek + jnz chr25 ;dokud neni nula + add edi,4 ;dalsi sloupec + dec cl ;odecti citac sloupcu + jnz chr26 ;dokud neni nula +chr2end: ret ;konec + + public charsize_ +charsize_: ;esi - ukazatel na font + ;al - znak + and eax,0ffh + mov ax,[esi][eax*2] + or ax,ax + jz chsend + add esi,eax + lodsw +chsend: and eax,0ffffh + ret + + public put_picture_ +put_picture_: ;esi - X + ;eax - Y + ;edi - obrazek + mov ecx,esi ;uchovej x v ecx + mov ebx,eax ;uchovej y v ebx + call getadr_ ;zjisti adresu bodu + mov esi,eax ;vloz ji do esi + xchg esi,edi ;prohod esi a edi aby obsahovali zpravne informace + xor eax,eax ;vynuluj pripadne bajty v horni polovine eax + lodsw ;nacti xs + mov _pictlen,eax + mov edx,eax ;z kopiruj jeste do pracovniho dx + add edx,ecx ;pricti k nemu souradnici + cmp edx,640 ;je-li vetsi nez max velikost obrazovky x + jc ppok1 ; + mov eax,640 ;pak za eax dosad plnou velikost + sub eax,ecx ;odecti souradnici +ppok1: mov ecx,eax ;vloz do ecx + lodsw ;totez pro y + mov edx,eax + add edx,ebx + cmp edx,480 + jc ppok2 + mov eax,480 + sub eax,ebx +ppok2: mov edx,eax + lodsw + mov ebx,edi + cmp al,15 + jnz pp_next + jmp pp15bit +pp_next:cmp al,8 + jnz pp_nxt2 + jmp pp8bit +pp_nxt2:ret + +pp15bit:mov eax,ecx +pp15bi1:shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,_pictlen + sub ecx,eax + shl ecx,1 + add esi,ecx + mov ecx,eax + add ebx,_linelen + mov edi,ebx + dec edx + jnz pp15bi1 + ret + +pp8bit: push ebp + mov ebp,ecx + mov ebx,esi + add esi,512 +pp8bit1:xor eax,eax + lodsb + or al,al + jz pp8bit2 + mov eax,[ebx+eax*2] + stosw +pp8bit4:dec ecx + jnz pp8bit1 + mov ecx,ebp + sub edi,ecx + sub edi,ecx + add edi,_linelen + sub esi,ebp + add esi,_pictlen + dec edx + jnz pp8bit1 + pop ebp + ret +pp8bit2:add edi,2 + jmp pp8bit4 + + public setPal_ +setPal_:mov edx,3c6h + mov al,255 + out dx,al + xor ah,ah +setpal1:mov edx,3c8h + mov al,ah + out dx,al + mov edx,3c9h + lodsb + out dx,al + lodsb + out dx,al + lodsb + out dx,al + inc ah + jne setPal1 + ret + +xvga_data: + DB 62h,4fh,50h,85h,56h,80h,0bh,3eh + DB 00h,40h,00h,00h,00h,00h,00h,28h + Db 0EAh,0ch,0DFh,28h,00h,0e7h,04h,0c3h,0ffh + + + + public init_lo_ +init_lo_: + mov eax,13h + int 10h ;{Inicializace modu 320x200x256} + + mov edx,3c4h ;{Zpristupneni Memory Mode reg.} + mov al,04h ;{04h -> 3c4h} + out dx,al + ;{Cte port 3c5h a modifikuje ho:} + mov bl,0f7h ;{Spristupni video ram pomoci} + inc edx ;{bitovych map - Map Mask Reg.} + in al,dx ;{rozdeleni na 4 bitove mapy} + and al,bl ;{jedna adresa reprezentuje 4 pixely} + out dx,al ;{(kazdy je v jedne ze 4 bitovych map)} + + mov ecx,0ffffh ;{Vynulovani segmentu 0A000h} + mov edi,0a0000h + mov al,00h + +int_lo1:rep stosb + + cli + + mov edx,3c4h ;{Port 3c4h -> Index Reset Reg.} + mov al,00h ;{Spristupni Reset Register} + out dx,al + + inc edx ;{Synchronizujici reset} + inc al + out dx,al ;{Port 3c2h ->} + mov edx,3c2h ;{VGA Miscellaneous Output Reg.} + mov al,0c7h ;{Nastavi 480 radku -bit 7,8=1,1} + out dx,al ;{ 28.322 MHz -bit 3,2=0,1} + + mov edx,3c5h ;{A opet reset} + mov al,03h + out dx,al + + sti + ;{Spristupni Color/VGA Data Reg.} + mov edx,3d4h ;{Port 3d4h} + mov al,11h + out dx,al + + inc edx ; {Bit 7 - Protect Bit} + in al,dx + and al,7fh + out dx,al + + + mov esi,offset xvga_data + mov ecx,19h + mov bl,00h +int_lo2: + mov edx,3d4h + mov al,bl + out dx,al + inc edx + mov al,byte ptr [cs:esi] + out dx,al + + inc si + inc bl + dec ecx + + jne int_lo2 + + ret + + + public Redraw_lo_ +Redraw_lo_: ;esi 614Kb obrazovka + ;edi lbuffer + ;ebx xlattable + + mov eax,1102h +rdrwlo2:mov edx,3c4h + out dx,ax + push eax + push esi + xor eax,eax + mov edi,0xa0000h + mov ecx,40*480 +rdrwlo1:lodsd + add esi,12 + shld edx,eax,16 + and eax,7bdeh ;odmaskuj pro soften + and edx,7bdeh + add eax,edx ;soften + shr eax,1 + mov al,[ebx+eax*2] ;vyber barvu z palety + mov dl,al + lodsd + add esi,12 + shld edx,eax,16 + and eax,7bdeh ;odmaskuj pro soften + and dx,7bdeh + add ax,dx ;soften + shr eax,1 + mov al,[ebx+eax*2] ;vyber barvu z palety + shr edx,8 + mov ah,dh + xchg ah,al + stosw + dec ecx + jnz rdrwlo1 + pop esi + pop eax + add esi,4 + rol ah,1 + jnc rdrwlo2 + ret + + public Redraw256_ +Redraw256_: ;esi - source + ;edi - target + ;ebx - xlat + + test ebx,1 + jz rdrwlo7 + inc ebx +rdrwlo7:xor eax,eax +rdrwlo4:mov ecx,480*65536 +rdrwlo6:mov cx,320 +rdrwlo5:mov edx,[esi] + and edx,7fff7fffh + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + xor ebx,1 + shr edx,16 + mov ah,[ebx+edx*2] + xor ebx,1 + stosw + dec cx + jnz rdrwlo5 + xor ebx,1 + sub ecx,65536 + jnz rdrwlo6 + ret + + public redraw32_ +redraw32_: ;esi source + ;edi target + ;ebx notused (xlat) + mov ecx,(640*480*2) shr 2 + rep movsd + ret + + + public redrawbox_lo_ +redrawbox_lo_: ;esi source + ;edi target + ;ebx xlat + ;ecx xs + ;edx,ys + shr ecx,1 + mov eax,1102h + xchg ecx,edi + shr ecx,1 + rol ah,cl + shr ecx,2 + add ecx,0a0000h + xchg ecx,edi + shl ecx,16 + and edx,0ffffh + or ecx,edx + push ebp + mov edx,3c4h ;edx adresa sequenceru + mov ebp,ecx ;ebp velikost ramce + sub ebp,10000h +rboxlo2:out dx,ax ;nastav bit roviny + push esi + push edi + push eax + push ebp ;bp pocet radku +rboxlo1:mov ecx,[esi] ;nacti dve barvy + shld eax,ecx,16 ;presun horni pulku do ecx + and eax,7bdfh ;odmaskuj pro soften + and ecx,7bdfh + add eax,ecx ;soften + shr eax,1 ;/2 + mov al,[ebx+eax*2] ;vyber barvu z palety + mov [edi],al ;zapis + add esi,_linelen ;dalsi radek + add edi,80 + dec bp ;dokud to neni vsechno + jnz rboxlo1 + pop ebp + pop eax + pop edi + pop esi + add esi,4 + rol ah,1 + adc edi,0 + sub ebp,10000h + jnc rboxlo2 + pop ebp + ret + + + public Redrawbox256_ +Redrawbox256_: ;esi - source + ;edi - target + ;ebx - xlat + ;ecx - ys + ;edx - xs + + shl ecx,16 + shr edx,1 + mov cx,dx + test ebx,1 + jz rboxlo7 + inc ebx +rboxlo7:xor eax,eax +rboxlo6:push ecx + push esi + push edi +rboxlo5:mov edx,[esi] + and edx,07fff7fffh + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + xor ebx,1 + shr edx,16 + mov ah,[ebx+edx*2] + xor ebx,1 + stosw + dec cx + jnz rboxlo5 + pop edi + pop esi + pop ecx + add esi,_linelen + add edi,640 + xor ebx,1 + sub ecx,65536 + test ecx,0ffff0000h + jnz rboxlo6 + ret + + public redrawbox32_ +redrawbox32_: ;esi source + ;edi target + ;ebx xs + ;edx ys + shr ebx,1 +rbox32: mov ecx,ebx + rep movsd + mov ecx,ebx + shl ecx,2 + sub esi,ecx + sub edi,ecx + add esi,_linelen + add edi,_linelen + dec edx + jnz rbox32 + ret + + public get_picture_ +get_picture_: ;esi - X + ;eax - Y + ;ebx - xs + ;ecx - ys + ;edi - obrazek + mov [edi],ebx ;zapis velikost obrazku + mov [edi+2],ecx + mov ecx,esi ;uchovej x v ecx + mov ebx,eax ;uchovej y v ebx + call getadr_ ;zjisti adresu bodu + mov esi,eax ;vloz ji do esi + xor eax,eax ;vynuluj pripadne bajty v horni polovine eax + mov ax,[edi];vem velikost x + add edi,2 + mov _pictlen,eax + mov edx,eax ;z kopiruj jeste do pracovniho dx + add edx,ecx ;pricti k nemu souradnici + cmp edx,640 ;je-li vetsi nez max velikost obrazovky x + jc gpok1 ; + mov eax,640 ;pak za eax dosad plnou velikost + sub eax,ecx ;odecti souradnici +gpok1: mov ecx,eax ;vloz do ecx + mov ax,[edi];vem velikost y + add edi,2 + mov edx,eax + add edx,ebx + cmp edx,480 + jc gpok2 + mov eax,480 + sub eax,ebx +gpok2: mov edx,eax + mov ax,15 ;nastav typ 15 + stosw ;zapis + mov ebx,esi ;uloz esi jeste do ebx +gp15bit:mov eax,ecx ;uloz ecx jeste do eax +gp15bi1:shr ecx,1 ;pocet dvojic bodu + rep movsd ;presun do pameti + rcl ecx,1 ;pokud zbyl jeste jeden + rep movsw ;tak ted + mov ecx,_pictlen + sub ecx,eax + shl ecx,1 + add edi,ecx ;jdi na dalsi radku v obrazku + mov ecx,eax ;obnov counter + add ebx,_linelen ;jdi na dalsi radku na obrazovce + mov esi,ebx ;obnov esi + dec edx ;dokud neni konec + jnz gp15bi1 + ret + + public hor_line_xor_ +Hor_line_xor_: ;EAX - Y ESI - X1 ECX - X2 + call getadr_ ;eax obsahuje adresu bodu + shr esi,1 + cmp ecx,esi ;x2>x1 + jnc xhorlin1 + xchg ecx,esi ;jestli ne tak je prohod +xhorlin1:sub ecx,esi ;xs=x2-x1+1 + inc ecx ; + mov edi,eax ;esi je adresa + mov ax,_curcolor ;nacti barvu +xhorlin2:xor [edi],ax + add edi,2 + dec ecx + jnz xhorlin2 + ret + +public ver_line_xor_ +ver_line_xor_: ;EAX - Y1 ESI - X ECX - Y2 + cmp ecx,eax ;y2>y1 + jnc xverlin1 + xchg ecx,eax ;jestli ne tak je prohod +xverlin1:sub ecx,eax + inc ecx + call getadr_ ;eax obsahuje adresu bodu + mov esi,eax + mov ax,_curcolor ;nacti barvu +xverlin2:xor [esi],ax ;kresli caru po bodech + add esi,_linelen + dec ecx + jnz xverlin2 + ret + +public switchmap_ ;eax - bank +switchmap_: + cmp eax,_lastbank + jz swbnk1 + pushad + mov _lastbank,eax + call switchvesabank_ + popad +swbnk1: ret + +public mapvesaadr_ ;edi - adr +mapvesaadr_: + push eax + push ecx + mov eax,edi + mov ecx,_granuality + shr eax,cl + call switchmap_ + pop ecx + pop eax + and edi,_gran_mask + add edi,0xa0000 + ret + +mapvesaadr macro + push eax + push ecx + mov eax,edi + mov ecx,_granuality + shr eax,cl + call switchmap_ + pop ecx + pop eax + and edi,_gran_mask + add edi,0xa0000 +endm + + + public redraw32b_ +redraw32b_: ;esi source + ;edi target + ;ebx notused (xlat) + xor eax,eax +rdrw32b:mov ebx,480 +rdrw32b1:mov edi,eax + call mapvesaadr_ + mov ecx,320 + rep movsd + add eax,2048 + dec ebx + jnz rdrw32b1 + ret + + + public redrawbox32b_ +redrawbox32b_: ;esi source + ;edi target + ;ebx xs + ;edx ys + mov eax,edi +rbox32b:mov edi,eax + call mapvesaadr_ + mov ecx,ebx + shr ecx,1 + rep movsd + rcl ecx,1 + rep movsw + mov ecx,ebx + shl ecx,1 + sub esi,ecx + add eax,2048 + add esi,_linelen + dec edx + jnz rbox32b + ret + +swap_at_end macro reg16,reg32 + local sw1,sw2 + +sw2: movzx eax,reg16 ;nacti 16 bitovou cast registru + dec eax ;sniz ke kontrole o 1 + cmp eax,_gran_mask ;kontrola zda je vetsi nebo rovny masce + jc sw1 ;kdyz ne tak preskoc na sw1 + mov eax,_lastbank ;vem cislo banky + inc eax ;pricti jednicku + mov _lastbank,eax ;vloz zpatky do banky + pushad + call switchvesabank_ ;prepni banku + popad + sub reg32,_gran_mask ;odecti delku stranky od cele adresy + dec reg32 +sw1: +endm + public Redraw256b_ +Redraw256b_: ;esi - source + ;edi - target + ;ebx - xlat + xor edi,edi + call mapvesaadr_ + xor eax,eax +rdrwlb4:mov ecx,480*65536 +rdrwlb6:mov cx,320 +rdrwlb5:mov edx,[esi] + and edx,7fff7fffh + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + shr edx,16 + xor ebx,1 + mov ah,[ebx+edx*2] + stosw + swap_at_end di,edi + xor ebx,1 + dec cx + jnz rdrwlb5 + xor ebx,1 + sub ecx,65536 + jnz rdrwlb6 + ret + + public Redrawbox256b_ +Redrawbox256b_: ;esi - source + ;edi - target + ;ebx - xlat + ;ecx - ys + ;edx - xs + + shl ecx,16 + shr edx,1 + mov cx,dx + test ebx,1 + jz rboxlb7 + inc ebx +rboxlb7:xor eax,eax +rboxlb6:push ecx + push esi + push edi + call mapvesaadr_ +rboxlb5:mov edx,[esi] + and edx,7fff7fffh + add esi,4 + mov ax,dx + mov al,[ebx+eax*2] + shr edx,16 + xor ebx,1 + mov ah,[ebx+edx*2] + stosw + swap_at_end di,edi + xor ebx,1 + dec cx + jnz rboxlb5 + pop edi + pop esi + pop ecx + add esi,_linelen + add edi,640 + xor ebx,1 + sub ecx,65536 + test ecx,0ffff0000h + jnz rboxlb6 + ret + + public Redraw16_plane +Redraw16_plane: ;esi - source + ;edi - target (A0000h) + ;ebx - xlat + ;ebp - planenum (jednicka v prislusnem bitu) + mov ecx,640*480 + mov edi,SEGA000 +rdrw16_l1: + shl eax,1 + movzx edx,word ptr[esi] + test [ebx+edx*2],ebp + jz rdrw16_s + or eax,1 +rdrw16_s: + add esi,2 + dec ecx + test ecx,15 + jnz rdrw16_l1 + xchg al,ah + test ecx,31 + jnz rdrw16_l1 + rol eax,16 + stosd + or ecx,ecx + jnz rdrw16_l1 + ret + + public Redraw16_ +Redraw16_: + + push ebp + push esi + mov edx,3c4h + mov eax,0802h + mov ebp,8h + out dx,ax + call Redraw16_plane + pop esi + push esi + mov edx,3c4h + mov eax,0402h + mov ebp,4h + out dx,ax + call Redraw16_plane + pop esi + push esi + mov edx,3c4h + mov eax,0202h + mov ebp,2h + out dx,ax + call Redraw16_plane + pop esi + mov edx,3c4h + mov eax,0102h + mov ebp,1h + out dx,ax + call Redraw16_plane + pop ebp + ret + +;Redraw16_: + push ebp + mov edx,3c4h + mov eax,0f02h + out dx,ax + mov edx,3ceh + mov eax,0205h + out dx,ax + mov eax,8008h + mov edi,SEGA000 + mov ebp,640*480 +rdw16: movzx ecx,word ptr[esi] + mov cl,byte ptr [ebx+ecx*2] + out dx,ax + mov [edi],cl + add esi,2 + ror ah,1 + adc edi,0 + dec ebp + jnz rdw16 + pop ebp + mov eax,0005h + out dx,ax + mov eax,0ff08h + out dx,ax + ret + + public Redraw16box_plane + ;esi - pozice + ;edi - output + ;ecx - ch = xs, hodni ecx=ys + ;esi - source + ;ebx - xlat + ;ebp - planenum (jednicka v prislusnem bitu) +redraw16box_plane: + sub ecx,10000h +rbx16_l1: + mov cl,ch + push esi + push edi +rbx16_l2: + mov ah,8 +rbx16_l3: + shl al,1 + movzx edx,word ptr[esi] + test [ebx+edx*2],ebp + jz rbx16_s + or al,1 +rbx16_s: + add esi,2 + dec ah + jnz rbx16_l3 + stosb + dec cl + jnz rbx16_l2 + pop edi + pop esi + add esi,1280 + add edi,80 + sub ecx,10000h + jnc rbx16_l1 + ret + + public Redrawbox16_ + ;esi - pozice + ;edi - output + ;ecx - xs + ;edx - ys + ;ebx - xlat +Redrawbox16_: + push ebp + mov eax,esp + push esi + push edi + shl ecx,16 + and edx,0ffh + shl edx,8 + or ecx,edx + push ecx + push eax + mov edx,3c4h + mov eax,0802h + out dx,ax + mov ebp,8 + call Redraw16box_plane + mov ebp,esp + mov ecx,[ebp+4] + mov edi,[ebp+8] + mov esi,[ebp+12] + mov edx,3c4h + mov eax,0402h + out dx,ax + mov ebp,4 + call Redraw16box_plane + mov ebp,esp + mov ecx,[ebp+4] + mov edi,[ebp+8] + mov esi,[ebp+12] + mov edx,3c4h + mov eax,0202h + out dx,ax + mov ebp,2 + call Redraw16box_plane + mov ebp,esp + mov ecx,[ebp+4] + mov edi,[ebp+8] + mov esi,[ebp+12] + mov edx,3c4h + mov eax,0102h + out dx,ax + mov ebp,1 + call Redraw16box_plane + pop esp + pop ebp + ret + + + +public redraw32bb_ +Redraw32bb_: + ;esi source + ;edi target + + mov ebx,(640*480)*2 ;ebx je velikost obrazovky + mov edx,_gran_mask + inc edx +rd32bb2:mov ecx,ebx ;ecx je velikost prenaseneho bloku + cmp ecx,edx ;kontrola zda li se prenasi prez stranku + jc rd32bb1 ;pokud ne pa ecx==ebx + mov ecx,edx ;jinak prenos stranky +rd32bb1:mov eax,edi ;uchovej edi + sub ebx,ecx ;ve tvaru o ecx vetsi (po prenosu + add eax,ecx ;a ebx sniz o prenaseny pocet + shr ecx,2 ;prenos probiha ve dword rezimu + mapvesaadr ;mapuj stranku edi=>edi + rep movsd ;prenos pameti + mov edi,eax ;obnov edi + or ebx,ebx ;test ebx na nulu + jnz rd32bb2 ;konec + ret + + +public redrawbox32bb_ +redrawbox32bb_: + ;esi source + ;edi target + ;ebx xs + ;edx ys + + shl ebx,1 ;delka je *2 +rdb32bb3:mov eax,edi ;precti adresu + and eax,_gran_mask ;maskuj stranku + sub eax,_gran_mask ;eax je pocet bajtu do nasledujiciho prenuti stranky + neg eax ;+1 + inc eax + push ebx ;uchovej delku ctverce v zasobniku +rdb32bb2:mov ecx,ebx ;vem minimum z cisel ebx a eax a dej to ecx + cmp ecx,eax + jc rdb32bb1 + mov ecx,eax +rdb32bb1:sub ebx,ecx ;odecti delku prenasenych bajtu + add edi,ecx ;pricti delku k adrese + push edi ;uloz to do sp + sub edi,ecx ;sniz adresu na puvodni hodnotu + shr ecx,2 ;del ecx 4 (presun dvojslov) + mapvesaadr ;namapuj adresu a banku + rep movsd ;PRESUN + pop edi ;obnov adresu + or ebx,ebx ;kontrola zda je prenesen radek + jnz rdb32bb2 ;ne, opakuj od urceni minima + pop ebx ;ano, obnov delku ctverce ze zasobniku + mov ecx,1280 ;od 1280 (640*2) odecti + sub ecx,ebx ;delku radky + add edi,ecx ;pricti to jak k cili + add esi,ecx ; tak ke zdroji + dec edx ;sniz citac radku + jnz rdb32bb3 ;dokud neni 0 + ret +_TEXT ends +END diff --git a/LIBS/BLDICONS.C b/LIBS/BLDICONS.C new file mode 100644 index 0000000..64cca04 --- /dev/null +++ b/LIBS/BLDICONS.C @@ -0,0 +1,82 @@ +#include +#include +#include +#include "memman.h" +#include "pcx.h" + +FILE *src,*trg,*scr; +#define IKNNAME "IKONY%02d.LIB" +#define IKONSINLIB 17 +#define PCXSIZE (2+2+2+512+45*55) +int icount=6; +char szBuff[65536]; + +void Error(char *text,char *param) + { + printf(text,param); + puts(""); + exit(1); + } + +void ReadScript(char *script) + { + int i; + int j=0; + char *pcx; + unsigned short *wpcx; + scr=fopen(script,"rt"); + if (scr==NULL) Error("Nemohu otevrit soubor: %s",script); + i=fscanf(scr,"%s",szBuff); + while (i!=EOF) + { + if (open_pcx(szBuff,A_8BIT,&pcx)==-1) Error("Nemohu pracovat se souborem: %s",szBuff); + wpcx=(unsigned short *)pcx; + if (wpcx[0]!=45 && wpcx[1]!=55) Error("Ikona musi mit rozmety 45x55. Soubor: %s",szBuff); + if (j==0) + { + sprintf(szBuff,IKNNAME,icount++); + printf("Sestavuji soubor %s\n",szBuff); + trg=fopen(szBuff,"wb"); + if (trg==NULL) Error("Nelze zapisovat do souboru %s",szBuff); + } + if (!fwrite(pcx,PCXSIZE,1,trg)) Error("Chyba nastala pri zapisu do souboru %s",szBuff); + free(pcx); + j++; + if (j==18) + { + fclose(trg); + j=0; + } + i=fscanf(scr,"%s",szBuff); + } + if (j!=0) + { + void *p; + int s; + p=malloc(s=(18-j)*PCXSIZE); + memset(p,0,s); + fwrite(p,s,1,trg); + } + fcloseall(); + } + +void Help() + { + Error("Pouziti: \n" + "\n" + "BLDICONS