-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTalkEngine.p
391 lines (312 loc) · 7.8 KB
/
TalkEngine.p
1
unit TalkEngine; interfaceuses types, quickdraw, icons, DialogLord4; procedure TalkEngine_Init;procedure TalkEngine_SetFont ( FontN : integer; FontSize : integer);function TalkEngine_Play ( Id : longint; MyName : str255; TheIconId : longint; Charisma, canBeRepeated : boolean) : integer;implementationuses memory, windows, dialogs, resources, events, textutils, quickdrawtext, dreamtypes, cilindro, lowlevel, Dream3Display_Tools, Engine3D_NPCTools;CONST kMaxQandAs = 50; kEndsWithEncounter = 'E'; kDialogEnds = 'D'; kDialogContinues = 'G'; TalkDialogId = 999; TYPE { Struttura dati in memoria } OneAnswer = RECORD answer: String; reaction: Char; { D: dialog ends; E: ends with NCTR; G: goto } id, charisma: Integer { NCTR id for E; next Q&A ID for G } END; OneQandA = RECORD question: String; answers: ARRAY [1..4] OF OneAnswer END; WholeDialog = RECORD myIcon, hisIcon: Integer; myName, hisName: String; QandA: ARRAY [1..kMaxQandAs] OF OneQandA END; WholeDialogPtr = ^WholeDialog; FUNCTION ReadTalkResource (id: Integer) : WholeDialogPtr;CONST resTalk = 'Talk';VAR myTalk: Handle; scanner: Ptr; spare: longint; numOfQA, i, j: Integer; result : WholeDialogPtr;BEGIN myTalk := MyGetResource (resTalk, id, TRUE, TRUE); scanner := myTalk^; result := WholeDialogPtr (newptr (sizeof (WholeDialog))); if result = nil then deathalert (erroutofmemory, memerror); WITH result^ DO BEGIN hisName := GetStringFromRes (scanner); hisIcon := GetIntegerfromres (scanner); spare := Getlongintfromres (scanner); numOfQA := GetIntegerFromRes (scanner); IF numofQA > kMaxQandAs THEN numOfQA := kMaxQandAs; { Sanity check } END; { with } FOR i := 1 TO numOfQA DO WITH result^.QandA[i] DO BEGIN question := GetStringFromRes (scanner); FOR j := 1 to 4 DO WITH answers[j] DO BEGIN answer := GetStringFromRes (scanner); reaction := Char (GetIntegerFromRes (scanner)); id := GetIntegerFromRes (scanner); charisma := GetIntegerFromRes (scanner); spare := GetIntegerFromRes (scanner); END; { for all answers } END; { for all Q&As } ReleaseResource (myTalk); ReadTalkResource := result;END;var FontId : integer; FSize : integer; TheTalkCursor : ccrsrhandle;procedure TalkEngine_Init;procedure GetTalkCursor;begin TheTalkCursor := getccursor (TalkDialogId); if TheTalkCursor = nil then erroralert (errmissingapplres, TalkDialogId);end;begin FontId := 0; FSize := 12; GetTalkCursor;end;procedure TalkEngine_SetFont ( FontN : integer; FontSize : integer);begin FontId := FontN; FSize := FontSize;end;function TalkEngine_Play ( Id : longint; MyName : str255; TheIconId : longint; Charisma, canBeRepeated : boolean) : integer;var TheDialog : dialogptr; TheChoice : longint; TheEvent : eventrecord; TheEnd : boolean; TheCurr : integer; TheEncounter : integer; myIconHandle, hisIconHandle : ciconhandle; Active : boolean; ThePort : grafptr; TheTalk : WholeDialogPtr; CurrentNode : 1..kMaxQandAs; CurrentAnswer : 1..4; procedure Respond2;var ThePoint : point; TheStr : str255; begin getmouse (ThePoint); backcolor (blackcolor); TheChoice := finddialogitem (TheDialog, ThePoint) + 1; if not (TheChoice in [6..9]) then TheChoice := 0; if TheChoice <> TheCurr then begin if TheCurr <> 0 then begin getitemtext (TheDialog, TheCurr, TheStr); forecolor (whitecolor); setitemtext (TheDialog, TheCurr, TheStr); end; if TheChoice in [6..9] then begin getitemtext (TheDialog, TheChoice, TheStr); forecolor (redcolor); setitemtext (TheDialog, TheChoice, TheStr); forecolor (whitecolor); TheCurr := TheChoice; end else TheCurr := 0; end;end;procedure SetTalkCursor;begin if TheTalkCursor <> nil then setccursor (TheTalkCursor) else InitCursor;end;procedure FillDialog;var I : longint; TheRect : rect; TheStr : str255; begin if Active then begin Respond2; exit (FillDialog); end; SetTalkCursor; beginupdate (TheDialog); if HisIconHandle <> nil then begin getitemrect (TheDialog, 1, TheRect); plotcicon (TheRect, HisIconHandle); end; if MyIconHandle <> nil then begin getitemrect (TheDialog, 2, TheRect); plotcicon (TheRect, MyIconHandle); end; forecolor (whitecolor); backcolor (blackcolor); textface ([bold]); setitemtext (TheDialog, 3, TheTalk^.hisName); setitemtext (TheDialog, 5, TheTalk^.myName); textface ([]); forecolor (whitecolor); backcolor (blackcolor); with TheTalk^.QandA [CurrentNode] do begin setitemtext (TheDialog, 4, question); for I := 1 to 4 do begin if answers [I].answer <> '' then if (not (Charisma)) and (answers [I].charisma <> 0) then setitemtext (TheDialog, 5 + I, '') else begin TheStr := answers [I].answer; if TheStr <> '>' then setitemtext (TheDialog, 5 + I, TheStr) else setitemtext (TheDialog, 5 + I, '') end else setitemtext (TheDialog, 5 + I, ''); end; end; forecolor (blackcolor); backcolor (whitecolor); Active := true; endupdate (TheDialog); if not ginbackground then validrect (TheDialog^.portrect);end;procedure DoNext;begin CurrentAnswer := TheChoice - 5; case TheTalk^.QandA [CurrentNode].answers [CurrentAnswer].reaction of kDialogContinues: begin CurrentNode := TheTalk^.QandA [CurrentNode].answers [CurrentAnswer].Id; FillDialog; end; kDialogEnds, kEndsWithEncounter: TheEnd := true; otherwise deathalert (errUnknownMdelAction, -1); end; Active := false; invalrect (TheDialog^.portrect);end;procedure Respond;var ThePoint : point;begin getmouse (ThePoint); if TheTalk^.QandA [CurrentNode].answers [1].answer = '>' then begin TheChoice := 6; DoNext; end else begin TheChoice := finddialogitem (TheDialog, ThePoint) + 1; if TheChoice in [6..9] then begin Active := false; DoNext; TheCurr := 0; end; end;end;begin TheTalk := ReadTalkResource (Id); TheTalk^.MyName := MyName; CurrentNode := 1; TheEnd := false; if TheIconId <> 0 then begin MyIconHandle := getcicon (TheIconId); if MyIconHandle = nil then DeathAlert (errMissingScenRes, TheIconId); end else MyIconHandle := nil; if TheTalk^.hisIcon <> 0 then begin HisIconHandle := getcicon (TheTalk^.hisIcon); if HisIconHandle = nil then DeathAlert (errMissingScenRes, TheTalk^.hisIcon); end else HisIconHandle := nil; if (TheTalk^.QandA [1].question <> '') then begin setdialogfont (FontId); TheDialog := getnewdialog (TalkDialogId, nil, pointer (-1)); getport (ThePort); if TheDialog = nil then deathalert (errmissingapplres, TalkDialogId); getport (ThePort); setport (TheDialog); textsize (FSize); Active := false; FillDialog; Active := false; TheCurr := 0; repeat if getnextevent (4 + 64, TheEvent) then if TheEvent.what <> 0 then begin case TheEvent.what of 2 : Respond 6 : FillDialog; end; Respond2; end else Respond2 else Respond2; until TheEnd; flushevents (everyevent, 0); setport (TheDialog); textsize (0); setport (ThePort); setdialogfont (0); disposedialog (TheDialog); if TheTalk^.QandA [CurrentNode].answers [CurrentAnswer].reaction = kEndsWithEncounter then TheEncounter := TheTalk^.QandA [CurrentNode].answers [CurrentAnswer].id else TheEncounter := 0; end else { questa roba si verifica sse la prima risposta nulla ma c' un Nctr subito dopo: va bene per gli NPC con cui non si parla ma che fanno scattare un incontro } if TheTalk^.QandA [1].answers [1].reaction = kEndsWithEncounter then TheEncounter := TheTalk^.QandA [1].answers [1].id else TheEncounter := 0; if CanBeRepeated then AdjustRepeated (Id); TalkEngine_Play := TheEncounter; disposeptr (ptr (TheTalk));end;end.