1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "mohawk/myst.h"
24 #include "mohawk/cursors.h"
25 #include "mohawk/graphics.h"
26 #include "mohawk/myst_areas.h"
27 #include "mohawk/sound.h"
28 #include "mohawk/video.h"
29 #include "mohawk/myst_stacks/dni.h"
30 
31 #include "common/system.h"
32 
33 namespace Mohawk {
34 namespace MystStacks {
35 
Dni(MohawkEngine_Myst * vm)36 Dni::Dni(MohawkEngine_Myst *vm) :
37 		MystScriptParser(vm, kDniStack),
38 		_notSeenAtrus(true),
39 		_atrusRunning(false),
40 		_waitForLoop(false),
41 		_atrusLeft(false),
42 		_atrusLeftTime(0),
43 		_loopStart(0),
44 		_loopEnd(0) {
45 	setupOpcodes();
46 }
47 
~Dni()48 Dni::~Dni() {
49 }
50 
setupOpcodes()51 void Dni::setupOpcodes() {
52 	// "Stack-Specific" Opcodes
53 	REGISTER_OPCODE(100, Dni, NOP);
54 	REGISTER_OPCODE(101, Dni, o_handPage);
55 
56 	// "Init" Opcodes
57 	REGISTER_OPCODE(200, Dni, o_atrus_init);
58 
59 	// "Exit" Opcodes
60 	REGISTER_OPCODE(300, Dni, NOP);
61 }
62 
disablePersistentScripts()63 void Dni::disablePersistentScripts() {
64 	_atrusRunning = false;
65 	_waitForLoop = false;
66 	_atrusLeft = false;
67 }
68 
runPersistentScripts()69 void Dni::runPersistentScripts() {
70 	if (_atrusRunning)
71 		atrus_run();
72 
73 	if (_waitForLoop)
74 		loopVideo_run();
75 
76 	if (_atrusLeft)
77 		atrusLeft_run();
78 }
79 
getVar(uint16 var)80 uint16 Dni::getVar(uint16 var) {
81 	switch(var) {
82 	case 0: // Atrus Gone (from across room)
83 		return _globals.ending == kAtrusLeaves;
84 	case 1: // Myst Book Status
85 		if (_globals.ending != kBooksDestroyed)
86 			return _globals.ending == kForgotPage;
87 		else
88 			return 2; // Linkable
89 	case 2: // Music Type
90 		if (_notSeenAtrus) {
91 			_notSeenAtrus = false;
92 			return _globals.ending != kBooksDestroyed && _globals.heldPage != kWhitePage;
93 		} else
94 			return 2;
95 	default:
96 		return MystScriptParser::getVar(var);
97 	}
98 }
99 
o_handPage(uint16 var,const ArgumentsArray & args)100 void Dni::o_handPage(uint16 var, const ArgumentsArray &args) {
101 	// Used in Card 5014 (Atrus)
102 
103 	// Find Atrus movie
104 	VideoEntryPtr atrus = _vm->findVideo(_video, kDniStack);
105 
106 	// Good ending and Atrus asked to give page
107 	if (_globals.ending == kAtrusWantsPage && atrus && atrus->getTime() > (uint)Audio::Timestamp(0, 6801, 600).msecs()) {
108 		_globals.ending = kAtrusLeaves;
109 		_globals.heldPage = kNoPage;
110 		_vm->setMainCursor(kDefaultMystCursor);
111 
112 		// Play movie end (atrus leaving)
113 		atrus->setBounds(Audio::Timestamp(0, 14813, 600), atrus->getDuration());
114 		atrus->setLooping(false);
115 
116 		_atrusLeft = true;
117 		_waitForLoop = false;
118 		_atrusLeftTime = _vm->getTotalPlayTime();
119 	}
120 }
121 
atrusLeft_run()122 void Dni::atrusLeft_run() {
123 	if (_vm->getTotalPlayTime() > _atrusLeftTime + 63333) {
124 		_video = "atrus2";
125 		_videoPos = Common::Point(215, 77);
126 		VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
127 		atrus->moveTo(_videoPos.x, _videoPos.y);
128 		atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 98000, 600));
129 
130 		_atrusRunning = false;
131 		_waitForLoop = true;
132 		_loopStart = 73095;
133 		_loopEnd = 98000;
134 
135 		// Good ending
136 		_globals.ending = kBooksDestroyed;
137 		_globals.bluePagesInBook = 63;
138 		_globals.redPagesInBook = 63;
139 
140 		_atrusLeft = false;
141 	}
142 }
143 
loopVideo_run()144 void Dni::loopVideo_run() {
145 	if (!_vm->_video->isVideoPlaying()) {
146 		VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
147 		atrus->moveTo(_videoPos.x, _videoPos.y);
148 		atrus->setBounds(Audio::Timestamp(0, _loopStart, 600), Audio::Timestamp(0, _loopEnd, 600));
149 		atrus->setLooping(true);
150 
151 		_waitForLoop = false;
152 	}
153 }
154 
atrus_run()155 void Dni::atrus_run() {
156 	if (_globals.ending == kAtrusLeaves) {
157 		// Wait for atrus to come back
158 		_atrusLeft = true;
159 	} else if (_globals.ending == kAtrusWantsPage) {
160 		// Atrus asking for page
161 		if (!_vm->_video->isVideoPlaying()) {
162 			_video = "atr1page";
163 			_videoPos = Common::Point(215, 76);
164 			VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
165 			atrus->moveTo(_videoPos.x, _videoPos.y);
166 			atrus->setLooping(true);
167 			atrus->setBounds(Audio::Timestamp(0, 7388, 600), Audio::Timestamp(0, 14700, 600));
168 		}
169 	} else if (_globals.ending != kForgotPage && _globals.ending != kBooksDestroyed) {
170 		if (_globals.heldPage == kWhitePage) {
171 			_video = "atr1page";
172 			_videoPos = Common::Point(215, 76);
173 			VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
174 			atrus->moveTo(_videoPos.x, _videoPos.y);
175 			atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 14700, 600));
176 
177 			_waitForLoop = true;
178 			_loopStart = 7388;
179 			_loopEnd = 14700;
180 
181 			// Wait for page
182 			_globals.ending = kAtrusWantsPage;
183 
184 		} else {
185 			_video = "atr1nopg";
186 			_videoPos = Common::Point(215, 77);
187 			VideoEntryPtr atrus = _vm->playMovie(_video, kDniStack);
188 			atrus->moveTo(_videoPos.x, _videoPos.y);
189 			atrus->setBounds(Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 46175, 600));
190 
191 			_atrusRunning = false;
192 			_waitForLoop = true;
193 			_loopStart = 30656;
194 			_loopEnd = 46175;
195 
196 			// Bad ending
197 			_globals.ending = kForgotPage;
198 		}
199 	} else if (!_vm->_video->isVideoPlaying()) {
200 		VideoEntryPtr atrus = _vm->playMovie("atrwrite", kDniStack);
201 		atrus->moveTo(215, 77);
202 		atrus->setLooping(true);
203 	}
204 }
205 
o_atrus_init(uint16 var,const ArgumentsArray & args)206 void Dni::o_atrus_init(uint16 var, const ArgumentsArray &args) {
207 	_atrusRunning = true;
208 }
209 
210 } // End of namespace MystStacks
211 } // End of namespace Mohawk
212