;rcharsav.sc   Quest for Glory...save character stats.

(script# rCharSave) ;840

(public
	CharSave		0
)

;; Bits in svMiscEquip
(define	FINESWORD_BIT 	$0001) ; fine sword
(define	FLAMESWORD_BIT	$0002) ; flaming sword
(define	COMPASS_BIT		$0003) ; compass
(define	PIN_BIT			$0004) ; spahire pin
(define	LAMP_BIT			$0008) ; brass lamp
(define	TOKEN_BIT		$0010) ; EOF token
(define	GLASSES_BIT		$0020) ; X-Ray Glasses

; things transferred from "Quest for Glory 1"
(define	BABA_BIT			$0030) ; Flag set from QG1
(define	SWORD_BIT		$0040) ; Sword
(define	CHAIN_BIT		$0080) ;
(define	PICK_BIT			$0100) ;
(define	TOOL_BIT			$0200) ;

(define	EXTRA_DATA	18)	; Data items other than stats and name
(define	CHECK_DATA	10)	; Data items that are in check sums

(define textWidth 220)

(local
;; local data for saving hero stats for next game
								 ;;;;;;;;;;;;;;;;;;start;;;;;;;;;;;;;;;;;;
	statsKey = $53			 ;;;;;;;;order dependent variables;;;;;;;;
	svCharType				 ;;;;;;;;order dependent variables;;;;;;;;
;**	svExperience			 ;;;;;;;;order dependent variables;;;;;;;;
	svHighDinar				 ;;;;;;;;order dependent variables;;;;;;;;
	svLowDinar				 ;;;;;;;;order dependent variables;;;;;;;;
	svScore					 ;;;;;;;;order dependent variables;;;;;;;;
	svMiscEquip				 ;;;;;;;;order dependent variables;;;;;;;;
	[codedStats NUM_ATTRIBS] ;;;;;;;;order dependent variables;;;;;;;;
	svDaggers				 ;;;;;;;;order dependent variables;;;;;;;;
	svHealingPill			 ;;;;;;;;order dependent variables;;;;;;;;
	svManaPill				 ;;;;;;;;order dependent variables;;;;;;;;
	svStaminaPill			 ;;;;;;;;order dependent variables;;;;;;;;
	svPoisonCurePill		 ;;;;;;;;order dependent variables;;;;;;;;	
	bogus0   = $a0			 ;;;;;;;;order dependent variables;;;;;;;;
	bogus1   = $3e			 ;;;;;;;;order dependent variables;;;;;;;;
	checkSum1				 ;;;;;;;;order dependent variables;;;;;;;;
	checkSum2				 ;;;;;;;;order dependent variables;;;;;;;;
	bogus2   = $2f			 ;;;;;;;;order dependent variables;;;;;;;;
	bogus3   = $90			 ;;;;;;;;order dependent variables;;;;;;;;
	bogus4   = $19			 ;;;;;;;;order dependent variables;;;;;;;;
	bogus5   = $a3			 ;;;;;;;;order dependent variables;;;;;;;;
	checkSumKey = $da		 ;;;;;;;;order dependent variables;;;;;;;;
								 ;;;;;;;;;;;;;;;;;;;end;;;;;;;;;;;;;;;;;;;
	check1
	check2
	[YNSTR 5]
	[yesOrNo 5]
	[heroFileName 44]
	[bigStr 400]
	hasSaved					 ;TRUE if hero saved
	[str 40]
	answer
)

(enum				;states of saveHero Script
	congrats
	playItAgain
	askSave
	getInfoFileName
	checkFile
	openFile
	writeHeroInfo
	writeComplete
	writeComplete2
	tryAgain
	saveDone
	checkSong
	redrawRoom
	goToCredits
)


(instance CharSave of Room
	(properties
		picture	pCredits1
		horizon	0
		style		IRISOUT
	)
	
	(method (dispose)
		(StatusLine code: dftStatusCode)
		(keyDownHandler delete: self)
		(super dispose:)
	)

	(method (init)
		(StatusLine
			code: endStatus,
			enable:
		)
		(keyDownHandler add: self)
		(super init: &rest)

		(customWindow
			back: vBLACK,
			color: vWHITE,
		)

		(songObj init:, hide:)
		(addToPics 
			add: frame1 frame2 frame3 frame4 frame5 frame6 frame7 frame8,
			eachElementDo: #init:,
			doit:
		)

		(cSound
			number: sStars,
			loop: -1,
			priority: 5,
			play:
		)

		; don't let'm control anything!
		(User canControl: FALSE, canInput: FALSE)

		(self setScript: saveHero)
		(songObj setScript: songScript)
	)

)
(instance heroinfo of File
	(properties
		name	{glory2.sav}
	)
)

(instance saveHero of Script

	(method (handleEvent event)
		(if
			(and
				(== (event type?) keyDown)
				(== (event message?) ENTER)
			)
			(if register
				(= register 0)
				(= cycles 1) 
				(event claimed: TRUE)
			)
		)
	)
	(method (changeState newState &tmp whichSkill oldDinar
											lineEndString oldExper retry)
		(switch (= state newState)
			(congrats
				(Format @heroFileName "a:glory2.sav")
				(if (>= score possibleScore)
					(Format @bigStr "CONGRATULATIONS!!\n
							You have successfully completed\n
							\"Quest for Glory II:__Trial by Fire\"\n
							with the maximum possible score, %d of %d!!\n
							We welcome you to the ranks of the few, the proud,
							the True Heroes!"
						possibleScore possibleScore
					)
					(Print @bigStr
						#window: customWindow
						#mode: teJustCenter
						#width: textWidth
						#dispose:
					)
				else
					(Print (Format @bigStr "Congratulations!__You have
								successfully completed\n
								\"Quest for Glory II:__Trial by Fire.\"\n
								Your final score was %d of %d possible Puzzle Points."
								score possibleScore
							)
						#window: customWindow
						#mode: teJustCenter
						#width: textWidth
						#dispose:
					)
				)
				(= register 1)
			)
			(playItAgain
				(Print "If you have not already done so,\n
						we encourage you to play\n
						\"Quest for Glory II\"\n
						again with the other two character types; many of the
						puzzles are different, or have alternate solutions."
						#window: customWindow
						#mode: teJustCenter
						#width: textWidth
						#dispose:
				)
				(= register 1)
			)
			(askSave
				(Print "In the meantime,\n you are already a winner!
						Please insert a writable disk in your floppy drive to
						save your winning Hero for use in\n
						\"Quest for Glory III:\n
						_Shadows of Darkness.\""
						#window: customWindow
						#mode: teJustCenter
						#width: textWidth
						#dispose:
				)
				(= register 1)
			)

			(getInfoFileName		 ; actually gets file name to save it as.
				(cls)
;**				(if (GetInput @heroFileName 30
;**							{Disk file in which to save your Hero.})
				(if 
					(Print 
						"Disk file in which to save your Hero."
						#window: customWindow
						#mode: teJustCenter
						#edit: @heroFileName 30
					)
					(heroinfo name: @heroFileName)
					(= cycles 2)
				else
					(self changeState: tryAgain)
				)
			)

			(checkFile		 ; checks if file already exists. and warns user
				(= answer 0)
				(if (!= (heroinfo open: fRead) NULL)
					(repeat 
						(= answer 
							(Print
								"File already exists.__Do 
								you wish to overwrite?"
								#title: {_WARNING!_}
								#mode: teJustCenter
								#window: Warning
								#button: {_NO_}	1
								#button: {_YES_}	2
							)
						)
						(if answer
							(break)
						)
					)
					(switch answer
						(1 (self changeState: getInfoFileName))
						(2 (= cycles 1))
					)
				else
					(= cycles 1)
				)
			)

			(openFile
				(if (heroinfo open: fTrunc)
					(heroinfo close:)
					(= seconds 2)
				else
					(Print (Format @bigStr "Could not create file -- %s."
							(heroinfo name?))
						#window: Warning
						#mode: teJustCenter
						#width: textWidth
					)
					(self changeState: tryAgain)
				)
			)					 

			(writeHeroInfo
				(if (not (heroinfo open: fAppend))
					(self  changeState: tryAgain)
					(return)
				)
				; it's always nice to know what the computer is doing
				(Print "Saving Character"
					#window: customWindow
					#mode: teJustCenter
					#dispose:
				)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

				; puts all ego stats in array (called codedStats) to save
				(for	((= whichSkill 0))
						(< whichSkill NUM_ATTRIBS)
						((++ whichSkill))
;**					(Printf "egoStat # %d = %d" whichSkill [egoStats whichSkill])
					(= [codedStats whichSkill] [egoStats whichSkill])
				)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;	 order dependant variables
				(= oldDinar [invNum iDinar])
				(= svCharType heroType)
;**				(= svExperience ( / [egoStats EXPER] 100))
				(= svHighDinar ( / oldDinar 100))
				(= svLowDinar  (mod oldDinar 100))
				(= svScore score)
				(= svMiscEquip 0)
				(if (ego has: iFineSword)		(|= svMiscEquip FINESWORD_BIT))
				(if (ego has: iSoulforge)		(|= svMiscEquip FLAMESWORD_BIT))
				(if (ego has: iCompass)			(|= svMiscEquip COMPASS_BIT))
				(if (ego has: iSapphPin)		(|= svMiscEquip PIN_BIT))
				(if (ego has: iBrassLamp)		(|= svMiscEquip LAMP_BIT))
				(if (ego has: iEOFToken)		(|= svMiscEquip TOKEN_BIT))
				(if (ego has: iGlasses)			(|= svMiscEquip GLASSES_BIT))
				(if (Btst fBabaFrog)				(|= svMiscEquip BABA_BIT))
				(if (ego has: iSword)			(|= svMiscEquip SWORD_BIT))
				(if (ego has: iChainMail)		(|= svMiscEquip CHAIN_BIT))
				(if (ego has: iLockPick)		(|= svMiscEquip PICK_BIT))
				(if (ego has: iThiefKit)		(|= svMiscEquip TOOL_BIT))

				(= svDaggers			[invNum iDagger])
				(= svHealingPill		[invNum iHealingPill])
				(= svManaPill			[invNum iManaPill])
				(= svStaminaPill		[invNum iStaminaPill])
				(= svPoisonCurePill	[invNum iPoisonCure])

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				(= check1 checkSumKey)
				(for	((= whichSkill 0))
						(< whichSkill (+ NUM_ATTRIBS CHECK_DATA))
						((+= whichSkill 2))
					(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 255))
					(+= check1 [statsKey (+ whichSkill 1)])
				)

				(= check2 0)
				(for	((= whichSkill 1))
						(< whichSkill (+ NUM_ATTRIBS CHECK_DATA))
						((+= whichSkill 2))
					(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 255))
					(+= check2 [statsKey (+ whichSkill 1)])
				)

				(&= check1 255)
				(&= check2 255)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				(= checkSum1 check1)
				(= checkSum2 check2)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				; exclusive-OR all stats into one number
				(for	((= whichSkill 0))
						(< whichSkill (+ NUM_ATTRIBS EXTRA_DATA))
						((++ whichSkill))
					(= [statsKey (+ whichSkill 1)] (& [statsKey (+ whichSkill 1)] 255))
					(^= [statsKey (+ whichSkill 1)] [statsKey whichSkill])
				)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
				(= lineEndString {*})		; Kludge for null string
				(StrAt lineEndString 0 `^J)

				; multiple strings can be sent at once
				(heroinfo writeString: @userName lineEndString)

				(for	((= whichSkill 1))
						( < whichSkill (+ NUM_ATTRIBS EXTRA_DATA 1))
						((++ whichSkill))
					(Format @bigStr "%2x" [statsKey whichSkill])
					(heroinfo writeString: @bigStr)
				)
				(heroinfo writeString: lineEndString)
				(heroinfo close:)
				(= seconds 2)
			)

			(writeComplete
				(if modelessDialog
					(modelessDialog dispose:)
				)
				(Print "The save character file has been created.__Save
						this disk for use with \"Quest for Glory III:__Shadows of Darkness\"
						from Sierra On-Line."
						#window: customWindow
						#width: textWidth
						#mode: teJustCenter
						#dispose:
				)
				(= register 1)
			)
			(writeComplete2
				(= hasSaved TRUE)
				(self changeState: saveDone)
;**				(= cycles 2)
			)

			(tryAgain
				(repeat
					(if
						(= retry
							(Print 
								"Do you wish to try saving
								your character again?"
								#button:	{_No_}	1
								#button:	{_Yes_}	2
								#window: customWindow
								#mode:	teJustCenter
							)
						)
						(switch retry
							(1 (= retry saveDone) (break))
							(2 
								(= retry getInfoFileName) 
								(= bogus0 $79)
								(= bogus1 $86)
								(= bogus2 $43)	
								(= bogus3 $88)	
								(= bogus4 $ad)	
								(= bogus5 $f0)	
								(break)
							)
						)
					)
				)
				(self changeState: retry)
			)
;**				(if (GetInput @YNSTR 2
;**							{If you wish to try saving your character again,
;**								type \"y\",	then ENTER.__Otherwise type \"n\",
;**								then ENTER.}
;**						)
;**					(if (StrCmp @YNSTR {y})
;**						(self changeState: saveDone)
;**					else
;**						(= bogus0 $79)
;**						(= bogus1 $86)
;**						(= bogus2 $43)	
;**						(= bogus3 $88)	
;**						(= bogus4 $ad)	
;**						(= bogus5 $f0)	
;**						(self changeState: getInfoFileName)
;**					)
;**				else
;**					(= cycles 2)
;**				)

;**			(badAnswer
;**				(Print "Please answer \"y\" or \"n\"."
;**						#window: Warning
;**						#mode: teJustCenter
;**				)
;**				(self  changeState: tryAgain)
;**			)

			(saveDone
				(Print "Thank you for playing\n 
						\"Quest for Glory II:__Trial by Fire,\"\n
						and congratulations again on winning.__We'll see you again soon in\n
						\"Quest for Glory III:\n
						Shadows of Darkness.\""
						#window: customWindow
						#width: textWidth
						#mode: teJustCenter
				)
				(= seconds 4)
			)
			(checkSong
				(if (== (miscSound number?) sMoon1)
					(= cycles 1)
				else
					(self setScript: waitForSong self)
				)
			)
			(redrawRoom
				(curRoom drawPic: pCredits1 IRISOUT)
				(= cycles 1)
			)
			(goToCredits
				(curRoom newRoom: rClosingCredits)
			)
		)
	)
)

(instance endStatus of Code
	(method (doit strg)
		(if (== heroType PALADIN)
			(Format strg "____Congratulations, Paladin!__[score %d of %d]"
					score possibleScore)
		else
			(Format strg "_______Hero of Two Lands!__[score %d of %d]"
					score possibleScore)
		)
	)
)

(instance frame1 of PicView
	(properties
		view			242
		loop			0
		cel			0
		x				81
		y				33
	)
)

(instance frame2 of PicView
	(properties
		view			242
		loop			1
		cel			0
		x				239
		y				33
	)
)

(instance frame3 of PicView
	(properties
		view			242
		loop			0
		cel			1
		x				19
		y				94
	)
)

(instance frame4 of PicView
	(properties
		view			242
		loop			0
		cel			2
		x				20
		y				156
	)
)

(instance frame5 of PicView
	(properties
		view			242
		loop			0
		cel			3
		x				81
		y				189
	)
)

(instance frame6 of PicView
	(properties
		view			242
		loop			1
		cel			3
		x				238
		y				189
	)
)

(instance frame7 of PicView
	(properties
		view			242
		loop			1
		cel			2
		x				300
		y				156
	)
)

(instance frame8 of PicView
	(properties
		view			242
		loop			1
		cel			1
		x				301
		y				94
	)
)
(instance Warning of SysWindow
	(properties
		back: vRED
		color: vYELLOW
	)
)

(instance songObj of Prop)

(instance songScript of Script
	(method (changeState newState)
		(switchto (= state newState)
			(
				(= seconds 8)
			)
			(
				(spareSound
					number: sLowDrone,
					priority: 10,
					loop:	-1,
					play:
				)
				(= seconds 8)
			)
			(
				(if (== (saveHero script?) waitForSong)
					(waitForSong cue:)
				else
					(waitForSong start: 1)
				)
				(miscSound
					number: sMoon1,
					loop: -1,
					priority: 11,
					play:
				)
				(= cycles 1)
			)
			((self dispose:))
		)
	)
)

(instance waitForSong of Script
	(method (changeState newState)
		(switch (= state newState)
			(0 0)
			(1 (self dispose:))
		)
	)
)

