#include #include #include #include #include #include #include #include #include #include #include #include #include #define maxControls 10 #define sumControls 50 #define windowBase 200 #define dialogBase 300 #define menuBase 400 #define controlBase 500 #define numWindows 5 #define raceWind 0 #define classWind 1 #define statusWind 2 #define alignWind 3 #define statistWind 4 #define numRace 6 #define norace 0 #define human 1 #define elf 2 #define dwarf 3 #define gnome 4 #define hobbit 5 #define numClass 8 #define fighter 0 #define mage 1 #define priest 2 #define thief 3 #define bishop 4 #define samurai 5 #define lord 6 #define ninja 7 #define numStatus 8 #define healthy 0 #define afraid 1 #define asleep 2 #define paralysed 3 #define stoned 4 #define dead 5 #define ashes 6 #define lost 7 #define numAlign 4 #define noalign 0 #define nice 1 #define neutral 2 #define evil 3 #define numStatist 10 #define Strength 0 #define Intelligence 1 #define Piety 2 #define Vitality 3 #define Agility 4 #define Luck 5 #define Gold 6 #define Experience 7 #define ActHits 8 #define MaxHits 9 #define numDialogs 5 #define aboutDialog 0 #define saveDialog 1 #define charDialog 2 #define opWrDialog 3 #define ioErrDialog 4 #define saveItem 1 #define discardItem 2 #define cancelItem 3 #define numMenus 3 #define apMenu 0 #define fileMenu 1 #define charMenu 2 /* Start of character storage info */ #define charBlock 186 /* size of storage in file for each character */ #define nameLength 0 #define charName 1 #define raceLoc 33 #define classLoc 34 #define statusLoc 38 #define alignLoc 39 #define strengthLoc 40 #define IQLoc 41 #define pietyLoc 42 #define vitalityLoc 43 #define agilityLoc 44 #define luckLoc 45 #define goldLoc 54 #define experienceLoc 106 #define actHitsLoc 114 #define maxHitsLoc 116 /* Start of program info */ #define DlgTop 100 #define DlgLeft 85 MenuHandle myMenu[numMenus]; EventRecord curEvent; WindowRecord wRecord; WindowPtr curWindow, myWindow[numWindows]; ControlHandle curControl, myControl[numWindows][maxControls]; Rect limitRect; short numControls[numWindows] = { numRace, numClass, numStatus, numAlign, numStatist }; short controlLoc[sumControls] = { raceLoc, classLoc, statusLoc, alignLoc, strengthLoc, IQLoc, pietyLoc, vitalityLoc, agilityLoc,luckLoc, goldLoc, experienceLoc, actHitsLoc, maxHitsLoc }; short curFile ; unsigned char stat[charBlock]; Str255 * chName; Boolean Dirty, ErrorFlag, FOPENED = FALSE; setmenus() /* set up menus */ { int menu; myMenu[apMenu] = GetMenu(1); AddResMenu(myMenu[apMenu], 'DRVR'); InsertMenu(myMenu[apMenu], 0); for (menu = fileMenu; menu <= charMenu; menu++) { myMenu[menu] = GetMenu(menuBase + menu); InsertMenu(myMenu[menu], 0); } for (menu = 1; menu <= 4; menu++) DisableItem(myMenu[charMenu], menu); DisableItem(myMenu[fileMenu], 2); DrawMenuBar(); } initialize() { InitGraf(&thePort); InitFonts(); SetEventMask(everyEvent - keyUpMask); FlushEvents(everyEvent, 0); InitWindows(); InitMenus(); TEInit(); InitDialogs(0L); SetCursor(&arrow); setmenus(); SetRect(&limitRect, 4, 24, 508, 338); curWindow = 0L; } IOCheck(resCode) /* check for IO errors */ OSErr resCode; { int alertDlg, ignore; long longresult; Str255 * errString; switch (resCode) { case noErr : return; case opWrErr : alertDlg = opWrDialog; break; default : alertDlg = ioErrDialogg; longresult = resCode; NumToString(longresult, errString); ParamText(errString, "\P ", "\P ", "\P "); } InitCursor(); ignore = StopAlert(dialogBase + alertDlg, 0L); ErrorFlag = TRUE; } openfile() /* ask for file to open */ { Point dlgOrigin; char fType[30]; SFReply theReply; OSErr resultCode; SetPt(&dlgOrigin, DlgTop, DlgLeft); strcpy(fType, "SAVE"); SFGetFile(pass(dlgOrigin), "\P ", 0L, 1, fType, 0L, &theReply); if (theReply.good) { resultCode = FSOpen(theReply.fName, theReply.vRefNum, &curFile); IOCheck(resultCode); FOPENED = TRUE; EnableItem(myMenu[fileMenu], 2); DisableItem(myMenu[fileMenu], 1); EnableItem(myMenu[charMenu], 1); } } closeDA() /* close a desk accesory */ { WindowPeek whichWindow; int accNum; whichWindow = (WindowPeek) FrontWindow(); accNum = whichWindow->windowKind; CloseDeskAcc(accNum); } closewindows() /* close all windows */ { int window; for (window = raceWind; window <= statistWind; window++) DisposeWindow(myWindow[window]); curWindow = 0L; } closefile() /* close a file */ { int theItem; OSErr resultCode; if ((curWindow != 0L) && (FrontWindow() == curWindow)) closewindows(); if (FrontWindow() != 0L) closeDA(); resultCode = FSClose(curFile); FOPENED = FALSE; DisableItem(myMenu[charMenu], 1); EnableItem(myMenu[fileMenu], 1); DisableItem(myMenu[fileMenu], 2); } getchname(theName) /* get character to edit */ Str255 * theName; { DialogPtr charDlg; Handle IHandle; Rect IRect; int itemNum, IType; charDlg = GetNewDialog(dialogBase + charDialog, 0L, -1L); do ModalDialog(0L, &itemNum); while ((itemNum != OK) && (itemNum != Cancel)); if (itemNum == Cancel) { theName->length = 3; strcpy(&(theName->text), "???"); } else { GetDItem(charDlg, 4, &IType, &IHandle, &IRect); GetIText(IHandle, theName); } DisposDialog(charDlg); } updateStats() /* draws statistics on window */ { static char * slabel[10] = { "strength ", "intellect ", "piety ", "vitality ", "agility ", "luck ", "gold ", "experience", "actual HPs", "max HPs " }; static int hp[10] = { 15, 15, 15, 260, 260, 260, 15, 15, 260, 260 }, vp[10] = { 34, 59, 84, 34, 59, 84, 134, 159, 134, 159 }; int label; SetPort(myWindow[statistWind]); for (label = Strength; label <= MaxHits; label++) { MoveTo(hp[label], vp[label]); DrawText(slabel[label], 0, 10); } } scale(ItoL, ip, lp) /* scales ints <-> longs */ unsigned char ItoL; unsigned int * ip; unsigned long * lp; { float tmp; if (ItoL) { tmp = ((float) *ip)/32000; *lp = 2147483000*tmp; } else { tmp = ((float) *lp)/2147483000; *ip = 32000*tmp; } } openwindows() /* opens all windows */ { int wID, cID, * intPtr, tmp, ctlCount = 0, localBase = controlBase; for (wID = raceWind; wID <= statistWind; wID++) { myWindow[wID] = GetNewWindow(windowBase + wID, 0L, -1L); for (cID = 0; cID < numControls[wID]; cID++) myControl[wID][cID] = GetNewControl(localBase + cID, myWindow[wID]); if (wID < statistWind) SetCtlValue(myControl[wID][stat[controlLoc[wID]]], 1); else { for (cID = 0; cID < numControls[wID]; cID++) if (cID < Gold) SetCtlValue(myControl[wID][cID], stat[controlLoc[wID + cID]]); else if (cID != Experience) { intPtr = &(stat[controlLoc[wID + cID]]); SetCtlValue(myControl[wID][cID], *intPtr); } else { scale(0, &tmp, &(stat[experienceLoc])); SetCtlValue(myControl[wID][cID], tmp); } updateStats(); } localBase += numControls[wID]; } curWindow = myWindow[wID - 1]; } rdchar() /* reads character stats from file */ { long blocklen = charBlock; int count, chindex; getchname(chName); if (chName->text[0] == '?') return; for (chindex = 0; chindex < 20; chindex++) { SetFPos(curFile, fsFromStart, chindex*blocklen); FSRead(curFile, &blocklen, stat); for (count = 1; count <= stat[0]; count++) if (stat[count] != chName->text[count - 1]) break; if (count > stat[0]) { SetFPos(curFile, fsFromMark, -blocklen); break; } } if (chindex < 20) { Dirty = FALSE; openwindows(); DisableItem(myMenu[fileMenu], 2); DisableItem(myMenu[charMenu], 1); for (count = 2; count <= 4; count++) EnableItem(myMenu[charMenu], count); } } wrchar() /* write character stats */ { long blocklen = charBlock; long curPos; FSWrite(curFile, &blocklen, stat); SetFPos(curFile, fsFromMark, -blocklen); Dirty = FALSE; } clchar() /* close a character */ { int theItem; if (Dirty) { ParamText(chName, "\P ", "\P ", "\P "); theItem = CautionAlert(dialogBase + saveDialog, 0L); switch (theItem) { case saveItem : wrchar(); break; case discardItem : break; case cancelItem : return; } } closewindows(); EnableItem(myMenu[fileMenu], 2); EnableItem(myMenu[charMenu], 1); for (theItem = 2; theItem <= 4; theItem++) DisableItem(myMenu[charMenu], theItem); } brag() /* do about stuff */ { int ignore; ignore = Alert(dialogBase + aboutDialog, 0L); } doCommand(eventloc) /* processes commands */ Point eventloc; { unsigned long mResult; char name[30]; short theMenu, theItem; long ticks; mResult = MenuSelect(pass(eventloc)); theMenu = mResult >> 16; theItem = mResult; switch (theMenu - menuBase) { case -399 : if (theItem == 1) brag(); else { GetItem(myMenu[apMenu], theItem, name); OpenDeskAcc(name); } break; case fileMenu : switch (theItem) { case 1 : openfile(); break; case 2 : closefile(); break; case 3 : if (Dirty) clchar(); if (FOPENED) closefile(); _exit(); } break; case charMenu : switch (theItem) { case 1 : rdchar(); break; case 2 : wrchar(); break; case 3 : clchar(); break; case 4 : clchar(); break; } break; default : break; } HiliteMenu(0); } pascal void scrollit(whichControl, whichPart) /* pascal action procedure for scrolling */ ControlHandle whichControl; int whichPart; { int change = 0; switch (whichPart) { case inUpButton :; case inPageUp : change--; break; case inDownButton :; case inPageDown : change++; break; default :; } if (whichPart) SetCtlValue(whichControl, GetCtlValue(whichControl) + change); } docontent() /* clicked in windows */ { int controlPart, control, window, button, localBase = controlBase; int * intPtr, tmpInt; if (curWindow != FrontWindow()) { SelectWindow(curWindow); return; } else { GlobalToLocal(&curEvent.where); if (controlPart = FindControl(pass(curEvent.where), curWindow, &curControl)) if (curWindow == myWindow[statistWind]) { Dirty = TRUE; if (controlPart == inThumb) controlPart = TrackControl(curControl, pass(curEvent.where), -1L); else controlPart = TrackControl(curControl, pass(curEvent.where), scrollit); for (control = Strength; control <= MaxHits; control++) if (curControl == myControl[statistWind][control]) if (control < Gold) stat[controlLoc[statistWind + control]] = GetCtlValue(curControl); else if (control != Experience) { intPtr = &(stat[controlLoc[statistWind + control]]); *intPtr = GetCtlValue(curControl); } else { tmpInt = GetCtlValue(curControl); scale(1, &tmpInt, &(stat[experienceLoc])); } } else if (TrackControl(curControl, pass(curEvent.where), -1L) == inCheckBox) { Dirty = TRUE; SetCtlValue(curControl, 1); for (window = raceWind; curWindow != myWindow[window]; window++) ; for (button = 0; button < numControls[window]; button++) if (myControl[window][button] == curControl) stat[controlLoc[window]] = button; else SetCtlValue(myControl[window][button], 0); } } } DoActivate() /* Handle activate events */ { WindowPeek whichWindow; WindowPtr thisWindow; ControlHandle whichControl; int windnum; thisWindow = (WindowPtr) curEvent.message; for (windnum = 0; windnum < numWindows; windnum++) if (thisWindow == myWindow[windnum]) break; if (windnum < numWindows) { whichWindow = (WindowPeek) thisWindow; SetPort(thisWindow); if (curEvent.modifiers & 1) { curWindow = thisWindow; for (whichControl = whichWindow->controlList; whichControl != 0L; whichControl = (*whichControl)->nextControl) HiliteControl(whichControl, 0); } else { for (whichControl = whichWindow->controlList; whichControl != 0L; whichControl = (*whichControl)->nextControl) HiliteControl(whichControl, 255); } } } DoUpdate() { WindowPtr thisWindow; int windnum; thisWindow = (WindowPtr) curEvent.message; for (windnum = 0; windnum < numWindows; windnum++) if (thisWindow == myWindow[windnum]) break; if (windnum < numWindows) { curWindow = thisWindow; BeginUpdate(curWindow); DrawControls(curWindow); if (windnum == statistWind) updateStats(); EndUpdate(curWindow); } } main() { int code; initialize(); for (;;) { SystemTask(); GetNextEvent(everyEvent, &curEvent); switch (curEvent.what) { case mouseDown : code = FindWindow(pass(curEvent.where), &curWindow); switch (code) { case inDesk : break; case inMenuBar : doCommand(pass(curEvent.where)); break; case inSysWindow: SystemClick(&curEvent, curWindow); break; case inDrag : DragWindow(curWindow, pass(curEvent.where), &limitRect); break; case inContent : docontent(); break; default : break; } break; case activateEvt : DoActivate(); break; case updateEvt : DoUpdate(); break; default : break; } } }