mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 09:49:11 +00:00
2059 lines
62 KiB
C++
2059 lines
62 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* This file is based on WME Lite.
|
|
* http://dead-code.org/redir.php?target=wmelite
|
|
* Copyright (c) 2011 Jan Nedoma
|
|
*/
|
|
|
|
#include "engines/wintermute/dcgf.h"
|
|
#include "engines/wintermute/AdGame.h"
|
|
#include "engines/wintermute/AdResponseBox.h"
|
|
#include "engines/wintermute/AdInventoryBox.h"
|
|
#include "engines/wintermute/AdSceneState.h"
|
|
#include "engines/wintermute/PartEmitter.h"
|
|
#include "engines/wintermute/BParser.h"
|
|
#include "engines/wintermute/BSurfaceStorage.h"
|
|
#include "engines/wintermute/BTransitionMgr.h"
|
|
#include "engines/wintermute/BObject.h"
|
|
#include "engines/wintermute/BSound.h"
|
|
#include "engines/wintermute/UIWindow.h"
|
|
#include "engines/wintermute/scriptables/ScValue.h"
|
|
#include "engines/wintermute/UIEntity.h"
|
|
#include "engines/wintermute/AdScene.h"
|
|
#include "engines/wintermute/AdEntity.h"
|
|
#include "engines/wintermute/AdActor.h"
|
|
#include "engines/wintermute/AdInventory.h"
|
|
#include "engines/wintermute/AdResponseContext.h"
|
|
#include "engines/wintermute/AdItem.h"
|
|
#include "engines/wintermute/BViewport.h"
|
|
#include "engines/wintermute/BFont.h"
|
|
#include "engines/wintermute/scriptables/ScEngine.h"
|
|
#include "engines/wintermute/BStringTable.h"
|
|
#include "engines/wintermute/AdSentence.h"
|
|
#include "engines/wintermute/AdResponse.h"
|
|
#include "engines/wintermute/scriptables/ScScript.h"
|
|
#include "engines/wintermute/scriptables/ScStack.h"
|
|
#include "engines/wintermute/BSprite.h"
|
|
#include "engines/wintermute/BFileManager.h"
|
|
#include "engines/wintermute/utils.h"
|
|
#include "common/str.h"
|
|
|
|
namespace WinterMute {
|
|
|
|
IMPLEMENT_PERSISTENT(CAdGame, true)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdGame::CAdGame(): CBGame() {
|
|
_responseBox = NULL;
|
|
_inventoryBox = NULL;
|
|
|
|
_scene = new CAdScene(Game);
|
|
_scene->SetName("");
|
|
RegisterObject(_scene);
|
|
|
|
_prevSceneName = NULL;
|
|
_prevSceneFilename = NULL;
|
|
_scheduledScene = NULL;
|
|
_scheduledFadeIn = false;
|
|
|
|
|
|
_stateEx = GAME_NORMAL;
|
|
|
|
_selectedItem = NULL;
|
|
|
|
|
|
_texItemLifeTime = 10000;
|
|
_texWalkLifeTime = 10000;
|
|
_texStandLifeTime = 10000;
|
|
_texTalkLifeTime = 10000;
|
|
|
|
_talkSkipButton = TALK_SKIP_LEFT;
|
|
|
|
_sceneViewport = NULL;
|
|
|
|
_initialScene = true;
|
|
_debugStartupScene = NULL;
|
|
_startupScene = NULL;
|
|
|
|
_invObject = new CAdObject(this);
|
|
_inventoryOwner = _invObject;
|
|
|
|
_tempDisableSaveState = false;
|
|
_itemsFile = NULL;
|
|
|
|
_smartItemCursor = false;
|
|
|
|
AddSpeechDir("speech");
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdGame::~CAdGame() {
|
|
Cleanup();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::Cleanup() {
|
|
int i;
|
|
|
|
for (i = 0; i < _objects.GetSize(); i++) {
|
|
UnregisterObject(_objects[i]);
|
|
_objects[i] = NULL;
|
|
}
|
|
_objects.RemoveAll();
|
|
|
|
|
|
for (i = 0; i < _dlgPendingBranches.GetSize(); i++) {
|
|
delete [] _dlgPendingBranches[i];
|
|
}
|
|
_dlgPendingBranches.RemoveAll();
|
|
|
|
for (i = 0; i < _speechDirs.GetSize(); i++) {
|
|
delete [] _speechDirs[i];
|
|
}
|
|
_speechDirs.RemoveAll();
|
|
|
|
|
|
UnregisterObject(_scene);
|
|
_scene = NULL;
|
|
|
|
// remove items
|
|
for (i = 0; i < _items.GetSize(); i++) Game->UnregisterObject(_items[i]);
|
|
_items.RemoveAll();
|
|
|
|
|
|
// clear remaining inventories
|
|
delete _invObject;
|
|
_invObject = NULL;
|
|
|
|
for (i = 0; i < _inventories.GetSize(); i++) {
|
|
delete _inventories[i];
|
|
}
|
|
_inventories.RemoveAll();
|
|
|
|
|
|
if (_responseBox) {
|
|
Game->UnregisterObject(_responseBox);
|
|
_responseBox = NULL;
|
|
}
|
|
|
|
if (_inventoryBox) {
|
|
Game->UnregisterObject(_inventoryBox);
|
|
_inventoryBox = NULL;
|
|
}
|
|
|
|
delete[] _prevSceneName;
|
|
delete[] _prevSceneFilename;
|
|
delete[] _scheduledScene;
|
|
delete[] _debugStartupScene;
|
|
delete[] _itemsFile;
|
|
_prevSceneName = NULL;
|
|
_prevSceneFilename = NULL;
|
|
_scheduledScene = NULL;
|
|
_debugStartupScene = NULL;
|
|
_startupScene = NULL;
|
|
_itemsFile = NULL;
|
|
|
|
delete _sceneViewport;
|
|
_sceneViewport = NULL;
|
|
|
|
for (i = 0; i < _sceneStates.GetSize(); i++) delete _sceneStates[i];
|
|
_sceneStates.RemoveAll();
|
|
|
|
for (i = 0; i < _responsesBranch.GetSize(); i++) delete _responsesBranch[i];
|
|
_responsesBranch.RemoveAll();
|
|
|
|
for (i = 0; i < _responsesGame.GetSize(); i++) delete _responsesGame[i];
|
|
_responsesGame.RemoveAll();
|
|
|
|
return CBGame::Cleanup();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::InitLoop() {
|
|
if (_scheduledScene && _transMgr->IsReady()) {
|
|
ChangeScene(_scheduledScene, _scheduledFadeIn);
|
|
SAFE_DELETE_ARRAY(_scheduledScene);
|
|
|
|
Game->_activeObject = NULL;
|
|
}
|
|
|
|
|
|
HRESULT res;
|
|
res = CBGame::InitLoop();
|
|
if (FAILED(res)) return res;
|
|
|
|
if (_scene) res = _scene->InitLoop();
|
|
|
|
_sentences.RemoveAll();
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::AddObject(CAdObject *Object) {
|
|
_objects.Add(Object);
|
|
return RegisterObject(Object);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::RemoveObject(CAdObject *Object) {
|
|
// in case the user called Scene.CreateXXX() and Game.DeleteXXX()
|
|
if (_scene) {
|
|
HRESULT Res = _scene->RemoveObject(Object);
|
|
if (SUCCEEDED(Res)) return Res;
|
|
}
|
|
|
|
for (int i = 0; i < _objects.GetSize(); i++) {
|
|
if (_objects[i] == Object) {
|
|
_objects.RemoveAt(i);
|
|
break;
|
|
}
|
|
}
|
|
return UnregisterObject(Object);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ChangeScene(const char *Filename, bool FadeIn) {
|
|
if (_scene == NULL) {
|
|
_scene = new CAdScene(Game);
|
|
RegisterObject(_scene);
|
|
} else {
|
|
_scene->ApplyEvent("SceneShutdown", true);
|
|
|
|
SetPrevSceneName(_scene->_name);
|
|
SetPrevSceneFilename(_scene->_filename);
|
|
|
|
if (!_tempDisableSaveState) _scene->SaveState();
|
|
_tempDisableSaveState = false;
|
|
}
|
|
|
|
if (_scene) {
|
|
// reset objects
|
|
for (int i = 0; i < _objects.GetSize(); i++) _objects[i]->Reset();
|
|
|
|
// reset scene properties
|
|
_scene->_sFXVolume = 100;
|
|
if (_scene->_scProp) _scene->_scProp->Cleanup();
|
|
|
|
HRESULT ret;
|
|
if (_initialScene && _dEBUG_DebugMode && _debugStartupScene) {
|
|
_initialScene = false;
|
|
ret = _scene->LoadFile(_debugStartupScene);
|
|
} else ret = _scene->LoadFile(Filename);
|
|
|
|
if (SUCCEEDED(ret)) {
|
|
// invalidate references to the original scene
|
|
for (int i = 0; i < _objects.GetSize(); i++) {
|
|
_objects[i]->InvalidateCurrRegions();
|
|
_objects[i]->_stickRegion = NULL;
|
|
}
|
|
|
|
_scene->LoadState();
|
|
}
|
|
if (FadeIn) Game->_transMgr->Start(TRANSITION_FADE_IN);
|
|
return ret;
|
|
} else return E_FAIL;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::AddSentence(CAdSentence *Sentence) {
|
|
_sentences.Add(Sentence);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::DisplaySentences(bool Frozen) {
|
|
for (int i = 0; i < _sentences.GetSize(); i++) {
|
|
if (Frozen && _sentences[i]->_freezable) continue;
|
|
else _sentences[i]->Display();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::FinishSentences() {
|
|
for (int i = 0; i < _sentences.GetSize(); i++) {
|
|
if (_sentences[i]->CanSkip()) {
|
|
_sentences[i]->_duration = 0;
|
|
if (_sentences[i]->_sound) _sentences[i]->_sound->Stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// high level scripting interface
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ChangeScene
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "ChangeScene") == 0) {
|
|
Stack->CorrectParams(3);
|
|
const char *Filename = Stack->Pop()->GetString();
|
|
CScValue *valFadeOut = Stack->Pop();
|
|
CScValue *valFadeIn = Stack->Pop();
|
|
|
|
bool TransOut = valFadeOut->IsNULL() ? true : valFadeOut->GetBool();
|
|
bool TransIn = valFadeIn->IsNULL() ? true : valFadeIn->GetBool();
|
|
|
|
ScheduleChangeScene(Filename, TransIn);
|
|
if (TransOut) _transMgr->Start(TRANSITION_FADE_OUT, true);
|
|
Stack->PushNULL();
|
|
|
|
|
|
//HRESULT ret = ChangeScene(Stack->Pop()->GetString());
|
|
//if(FAILED(ret)) Stack->PushBool(false);
|
|
//else Stack->PushBool(true);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LoadActor
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LoadActor") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CAdActor *act = new CAdActor(Game);
|
|
if (act && SUCCEEDED(act->LoadFile(Stack->Pop()->GetString()))) {
|
|
AddObject(act);
|
|
Stack->PushNative(act, true);
|
|
} else {
|
|
delete act;
|
|
act = NULL;
|
|
Stack->PushNULL();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LoadEntity
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LoadEntity") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CAdEntity *ent = new CAdEntity(Game);
|
|
if (ent && SUCCEEDED(ent->LoadFile(Stack->Pop()->GetString()))) {
|
|
AddObject(ent);
|
|
Stack->PushNative(ent, true);
|
|
} else {
|
|
delete ent;
|
|
ent = NULL;
|
|
Stack->PushNULL();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// UnloadObject / UnloadActor / UnloadEntity / DeleteEntity
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "UnloadObject") == 0 || strcmp(Name, "UnloadActor") == 0 || strcmp(Name, "UnloadEntity") == 0 || strcmp(Name, "DeleteEntity") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *val = Stack->Pop();
|
|
CAdObject *obj = (CAdObject *)val->GetNative();
|
|
RemoveObject(obj);
|
|
if (val->GetType() == VAL_VARIABLE_REF) val->SetNULL();
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CreateEntity
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "CreateEntity") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CAdEntity *Ent = new CAdEntity(Game);
|
|
AddObject(Ent);
|
|
if (!Val->IsNULL()) Ent->SetName(Val->GetString());
|
|
Stack->PushNative(Ent, true);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CreateItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "CreateItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CAdItem *Item = new CAdItem(Game);
|
|
AddItem(Item);
|
|
if (!Val->IsNULL()) Item->SetName(Val->GetString());
|
|
Stack->PushNative(Item, true);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DeleteItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "DeleteItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CAdItem *Item = NULL;
|
|
if (Val->IsNative()) Item = (CAdItem *)Val->GetNative();
|
|
else Item = GetItemByName(Val->GetString());
|
|
|
|
if (Item) {
|
|
DeleteItem(Item);
|
|
}
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// QueryItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "QueryItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CAdItem *Item = NULL;
|
|
if (Val->IsInt()) {
|
|
int Index = Val->GetInt();
|
|
if (Index >= 0 && Index < _items.GetSize()) Item = _items[Index];
|
|
} else {
|
|
Item = GetItemByName(Val->GetString());
|
|
}
|
|
|
|
if (Item) Stack->PushNative(Item, true);
|
|
else Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AddResponse/AddResponseOnce/AddResponseOnceGame
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "AddResponse") == 0 || strcmp(Name, "AddResponseOnce") == 0 || strcmp(Name, "AddResponseOnceGame") == 0) {
|
|
Stack->CorrectParams(6);
|
|
int id = Stack->Pop()->GetInt();
|
|
const char *text = Stack->Pop()->GetString();
|
|
CScValue *val1 = Stack->Pop();
|
|
CScValue *val2 = Stack->Pop();
|
|
CScValue *val3 = Stack->Pop();
|
|
CScValue *val4 = Stack->Pop();
|
|
|
|
if (_responseBox) {
|
|
CAdResponse *res = new CAdResponse(Game);
|
|
if (res) {
|
|
res->_iD = id;
|
|
res->SetText(text);
|
|
_stringTable->Expand(&res->_text);
|
|
if (!val1->IsNULL()) res->SetIcon(val1->GetString());
|
|
if (!val2->IsNULL()) res->SetIconHover(val2->GetString());
|
|
if (!val3->IsNULL()) res->SetIconPressed(val3->GetString());
|
|
if (!val4->IsNULL()) res->SetFont(val4->GetString());
|
|
|
|
if (strcmp(Name, "AddResponseOnce") == 0) res->_responseType = RESPONSE_ONCE;
|
|
else if (strcmp(Name, "AddResponseOnceGame") == 0) res->_responseType = RESPONSE_ONCE_GAME;
|
|
|
|
_responseBox->_responses.Add(res);
|
|
}
|
|
} else {
|
|
Script->RuntimeError("Game.AddResponse: response box is not defined");
|
|
}
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ResetResponse
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ResetResponse") == 0) {
|
|
Stack->CorrectParams(1);
|
|
int ID = Stack->Pop()->GetInt(-1);
|
|
ResetResponse(ID);
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ClearResponses
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ClearResponses") == 0) {
|
|
Stack->CorrectParams(0);
|
|
_responseBox->ClearResponses();
|
|
_responseBox->ClearButtons();
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetResponse
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetResponse") == 0) {
|
|
Stack->CorrectParams(1);
|
|
bool AutoSelectLast = Stack->Pop()->GetBool();
|
|
|
|
if (_responseBox) {
|
|
_responseBox->WeedResponses();
|
|
|
|
if (_responseBox->_responses.GetSize() == 0) {
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
if (_responseBox->_responses.GetSize() == 1 && AutoSelectLast) {
|
|
Stack->PushInt(_responseBox->_responses[0]->_iD);
|
|
_responseBox->HandleResponse(_responseBox->_responses[0]);
|
|
_responseBox->ClearResponses();
|
|
return S_OK;
|
|
}
|
|
|
|
_responseBox->CreateButtons();
|
|
_responseBox->_waitingScript = Script;
|
|
Script->WaitForExclusive(_responseBox);
|
|
_state = GAME_SEMI_FROZEN;
|
|
_stateEx = GAME_WAITING_RESPONSE;
|
|
} else {
|
|
Script->RuntimeError("Game.GetResponse: response box is not defined");
|
|
Stack->PushNULL();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetNumResponses
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetNumResponses") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (_responseBox) {
|
|
_responseBox->WeedResponses();
|
|
Stack->PushInt(_responseBox->_responses.GetSize());
|
|
} else {
|
|
Script->RuntimeError("Game.GetNumResponses: response box is not defined");
|
|
Stack->PushNULL();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// StartDlgBranch
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "StartDlgBranch") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
Common::String BranchName;
|
|
if (Val->IsNULL()) {
|
|
BranchName.format("line%d", Script->_currentLine);
|
|
} else BranchName = Val->GetString();
|
|
|
|
StartDlgBranch(BranchName.c_str(), Script->_filename == NULL ? "" : Script->_filename, Script->_threadEvent == NULL ? "" : Script->_threadEvent);
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// EndDlgBranch
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "EndDlgBranch") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
const char *BranchName = NULL;
|
|
CScValue *Val = Stack->Pop();
|
|
if (!Val->IsNULL()) BranchName = Val->GetString();
|
|
EndDlgBranch(BranchName, Script->_filename == NULL ? "" : Script->_filename, Script->_threadEvent == NULL ? "" : Script->_threadEvent);
|
|
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetCurrentDlgBranch
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetCurrentDlgBranch") == 0) {
|
|
Stack->CorrectParams(0);
|
|
|
|
if (_dlgPendingBranches.GetSize() > 0) {
|
|
Stack->PushString(_dlgPendingBranches[_dlgPendingBranches.GetSize() - 1]);
|
|
} else Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TakeItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "TakeItem") == 0) {
|
|
return _invObject->ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DropItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "DropItem") == 0) {
|
|
return _invObject->ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetItem") == 0) {
|
|
return _invObject->ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// HasItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "HasItem") == 0) {
|
|
return _invObject->ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// IsItemTaken
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "IsItemTaken") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
CScValue *val = Stack->Pop();
|
|
if (!val->IsNULL()) {
|
|
for (int i = 0; i < _inventories.GetSize(); i++) {
|
|
CAdInventory *Inv = _inventories[i];
|
|
|
|
for (int j = 0; j < Inv->_takenItems.GetSize(); j++) {
|
|
if (val->GetNative() == Inv->_takenItems[j]) {
|
|
Stack->PushBool(true);
|
|
return S_OK;
|
|
} else if (scumm_stricmp(val->GetString(), Inv->_takenItems[j]->_name) == 0) {
|
|
Stack->PushBool(true);
|
|
return S_OK;
|
|
}
|
|
}
|
|
}
|
|
} else Script->RuntimeError("Game.IsItemTaken: item name expected");
|
|
|
|
Stack->PushBool(false);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetInventoryWindow
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetInventoryWindow") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (_inventoryBox && _inventoryBox->_window)
|
|
Stack->PushNative(_inventoryBox->_window, true);
|
|
else
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetResponsesWindow
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetResponsesWindow") == 0 || strcmp(Name, "GetResponseWindow") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (_responseBox && _responseBox->_window)
|
|
Stack->PushNative(_responseBox->_window, true);
|
|
else
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LoadResponseBox
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LoadResponseBox") == 0) {
|
|
Stack->CorrectParams(1);
|
|
const char *Filename = Stack->Pop()->GetString();
|
|
|
|
Game->UnregisterObject(_responseBox);
|
|
_responseBox = new CAdResponseBox(Game);
|
|
if (_responseBox && !FAILED(_responseBox->LoadFile(Filename))) {
|
|
RegisterObject(_responseBox);
|
|
Stack->PushBool(true);
|
|
} else {
|
|
SAFE_DELETE(_responseBox);
|
|
Stack->PushBool(false);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LoadInventoryBox
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LoadInventoryBox") == 0) {
|
|
Stack->CorrectParams(1);
|
|
const char *Filename = Stack->Pop()->GetString();
|
|
|
|
Game->UnregisterObject(_inventoryBox);
|
|
_inventoryBox = new CAdInventoryBox(Game);
|
|
if (_inventoryBox && !FAILED(_inventoryBox->LoadFile(Filename))) {
|
|
RegisterObject(_inventoryBox);
|
|
Stack->PushBool(true);
|
|
} else {
|
|
delete _inventoryBox;
|
|
_inventoryBox = NULL;
|
|
Stack->PushBool(false);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LoadItems
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LoadItems") == 0) {
|
|
Stack->CorrectParams(2);
|
|
const char *Filename = Stack->Pop()->GetString();
|
|
bool Merge = Stack->Pop()->GetBool(false);
|
|
|
|
HRESULT Ret = LoadItemsFile(Filename, Merge);
|
|
Stack->PushBool(SUCCEEDED(Ret));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AddSpeechDir
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "AddSpeechDir") == 0) {
|
|
Stack->CorrectParams(1);
|
|
const char *Dir = Stack->Pop()->GetString();
|
|
Stack->PushBool(SUCCEEDED(AddSpeechDir(Dir)));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// RemoveSpeechDir
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "RemoveSpeechDir") == 0) {
|
|
Stack->CorrectParams(1);
|
|
const char *Dir = Stack->Pop()->GetString();
|
|
Stack->PushBool(SUCCEEDED(RemoveSpeechDir(Dir)));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SetSceneViewport
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SetSceneViewport") == 0) {
|
|
Stack->CorrectParams(4);
|
|
int X = Stack->Pop()->GetInt();
|
|
int Y = Stack->Pop()->GetInt();
|
|
int Width = Stack->Pop()->GetInt();
|
|
int Height = Stack->Pop()->GetInt();
|
|
|
|
if (Width <= 0) Width = _renderer->_width;
|
|
if (Height <= 0) Height = _renderer->_height;
|
|
|
|
if (!_sceneViewport) _sceneViewport = new CBViewport(Game);
|
|
if (_sceneViewport) _sceneViewport->SetRect(X, Y, X + Width, Y + Height);
|
|
|
|
Stack->PushBool(true);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
else return CBGame::ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CScValue *CAdGame::ScGetProperty(const char *Name) {
|
|
_scValue->SetNULL();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Type
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "Type") == 0) {
|
|
_scValue->SetString("game");
|
|
return _scValue;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Scene
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "Scene") == 0) {
|
|
if (_scene) _scValue->SetNative(_scene, true);
|
|
else _scValue->SetNULL();
|
|
|
|
return _scValue;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SelectedItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SelectedItem") == 0) {
|
|
//if(_selectedItem) _scValue->SetString(_selectedItem->_name);
|
|
if (_selectedItem) _scValue->SetNative(_selectedItem, true);
|
|
else _scValue->SetNULL();
|
|
|
|
return _scValue;
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// NumItems
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "NumItems") == 0) {
|
|
return _invObject->ScGetProperty(Name);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SmartItemCursor
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SmartItemCursor") == 0) {
|
|
_scValue->SetBool(_smartItemCursor);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryVisible
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryVisible") == 0) {
|
|
_scValue->SetBool(_inventoryBox && _inventoryBox->_visible);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryScrollOffset
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryScrollOffset") == 0) {
|
|
if (_inventoryBox) _scValue->SetInt(_inventoryBox->_scrollOffset);
|
|
else _scValue->SetInt(0);
|
|
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ResponsesVisible (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ResponsesVisible") == 0) {
|
|
_scValue->SetBool(_stateEx == GAME_WAITING_RESPONSE);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PrevScene / PreviousScene (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "PrevScene") == 0 || strcmp(Name, "PreviousScene") == 0) {
|
|
if (!_prevSceneName) _scValue->SetString("");
|
|
else _scValue->SetString(_prevSceneName);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PrevSceneFilename / PreviousSceneFilename (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "PrevSceneFilename") == 0 || strcmp(Name, "PreviousSceneFilename") == 0) {
|
|
if (!_prevSceneFilename) _scValue->SetString("");
|
|
else _scValue->SetString(_prevSceneFilename);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LastResponse (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LastResponse") == 0) {
|
|
if (!_responseBox || !_responseBox->_lastResponseText) _scValue->SetString("");
|
|
else _scValue->SetString(_responseBox->_lastResponseText);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// LastResponseOrig (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "LastResponseOrig") == 0) {
|
|
if (!_responseBox || !_responseBox->_lastResponseTextOrig) _scValue->SetString("");
|
|
else _scValue->SetString(_responseBox->_lastResponseTextOrig);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryObject
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryObject") == 0) {
|
|
if (_inventoryOwner == _invObject) _scValue->SetNative(this, true);
|
|
else _scValue->SetNative(_inventoryOwner, true);
|
|
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TotalNumItems
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "TotalNumItems") == 0) {
|
|
_scValue->SetInt(_items.GetSize());
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TalkSkipButton
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "TalkSkipButton") == 0) {
|
|
_scValue->SetInt(_talkSkipButton);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ChangingScene
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ChangingScene") == 0) {
|
|
_scValue->SetBool(_scheduledScene != NULL);
|
|
return _scValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// StartupScene
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "StartupScene") == 0) {
|
|
if (!_startupScene) _scValue->SetNULL();
|
|
else _scValue->SetString(_startupScene);
|
|
return _scValue;
|
|
}
|
|
|
|
else return CBGame::ScGetProperty(Name);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ScSetProperty(const char *Name, CScValue *Value) {
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SelectedItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "SelectedItem") == 0) {
|
|
if (Value->IsNULL()) _selectedItem = NULL;
|
|
else {
|
|
if (Value->IsNative()) {
|
|
_selectedItem = NULL;
|
|
for (int i = 0; i < _items.GetSize(); i++) {
|
|
if (_items[i] == Value->GetNative()) {
|
|
_selectedItem = (CAdItem *)Value->GetNative();
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
// try to get by name
|
|
_selectedItem = GetItemByName(Value->GetString());
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SmartItemCursor
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SmartItemCursor") == 0) {
|
|
_smartItemCursor = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryVisible
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryVisible") == 0) {
|
|
if (_inventoryBox) _inventoryBox->_visible = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryObject
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryObject") == 0) {
|
|
if (_inventoryOwner && _inventoryBox) _inventoryOwner->GetInventory()->_scrollOffset = _inventoryBox->_scrollOffset;
|
|
|
|
if (Value->IsNULL()) _inventoryOwner = _invObject;
|
|
else {
|
|
CBObject *Obj = (CBObject *)Value->GetNative();
|
|
if (Obj == this) _inventoryOwner = _invObject;
|
|
else if (Game->ValidObject(Obj)) _inventoryOwner = (CAdObject *)Obj;
|
|
}
|
|
|
|
if (_inventoryOwner && _inventoryBox) _inventoryBox->_scrollOffset = _inventoryOwner->GetInventory()->_scrollOffset;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// InventoryScrollOffset
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "InventoryScrollOffset") == 0) {
|
|
if (_inventoryBox) _inventoryBox->_scrollOffset = Value->GetInt();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TalkSkipButton
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "TalkSkipButton") == 0) {
|
|
int Val = Value->GetInt();
|
|
if (Val < 0) Val = 0;
|
|
if (Val > TALK_SKIP_NONE) Val = TALK_SKIP_NONE;
|
|
_talkSkipButton = (TTalkSkipButton)Val;
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// StartupScene
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "StartupScene") == 0) {
|
|
if (Value == NULL) {
|
|
delete[] _startupScene;
|
|
_startupScene = NULL;
|
|
} else CBUtils::SetString(&_startupScene, Value->GetString());
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
else return CBGame::ScSetProperty(Name, Value);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::PublishNatives() {
|
|
if (!_scEngine || !_scEngine->_compilerAvailable) return;
|
|
|
|
CBGame::PublishNatives();
|
|
|
|
_scEngine->ExtDefineFunction("Actor");
|
|
_scEngine->ExtDefineFunction("Entity");
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ExternalCall(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
|
|
CScValue *this_obj;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Actor
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "Actor") == 0) {
|
|
Stack->CorrectParams(0);
|
|
this_obj = ThisStack->GetTop();
|
|
|
|
this_obj->SetNative(new CAdActor(Game));
|
|
Stack->PushNULL();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Entity
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "Entity") == 0) {
|
|
Stack->CorrectParams(0);
|
|
this_obj = ThisStack->GetTop();
|
|
|
|
this_obj->SetNative(new CAdEntity(Game));
|
|
Stack->PushNULL();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// call parent
|
|
else return CBGame::ExternalCall(Script, Stack, ThisStack, Name);
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ShowCursor() {
|
|
if (_cursorHidden) return S_OK;
|
|
|
|
if (_selectedItem && Game->_state == GAME_RUNNING && _stateEx == GAME_NORMAL && _interactive) {
|
|
if (_selectedItem->_cursorCombined) {
|
|
CBSprite *OrigLastCursor = _lastCursor;
|
|
CBGame::ShowCursor();
|
|
_lastCursor = OrigLastCursor;
|
|
}
|
|
if (_activeObject && _selectedItem->_cursorHover && _activeObject->GetExtendedFlag("usable")) {
|
|
if (!_smartItemCursor || _activeObject->CanHandleEvent(_selectedItem->_name))
|
|
return DrawCursor(_selectedItem->_cursorHover);
|
|
else
|
|
return DrawCursor(_selectedItem->_cursorNormal);
|
|
} else return DrawCursor(_selectedItem->_cursorNormal);
|
|
} else return CBGame::ShowCursor();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::LoadFile(const char *Filename) {
|
|
byte *Buffer = _fileManager->ReadWholeFile(Filename);
|
|
if (Buffer == NULL) {
|
|
Game->LOG(0, "CAdGame::LoadFile failed for file '%s'", Filename);
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT ret;
|
|
|
|
_filename = new char [strlen(Filename) + 1];
|
|
strcpy(_filename, Filename);
|
|
|
|
if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing GAME file '%s'", Filename);
|
|
|
|
|
|
delete [] Buffer;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
TOKEN_DEF_START
|
|
TOKEN_DEF(GAME)
|
|
TOKEN_DEF(AD_GAME)
|
|
TOKEN_DEF(RESPONSE_BOX)
|
|
TOKEN_DEF(INVENTORY_BOX)
|
|
TOKEN_DEF(ITEMS)
|
|
TOKEN_DEF(ITEM)
|
|
TOKEN_DEF(TALK_SKIP_BUTTON)
|
|
TOKEN_DEF(SCENE_VIEWPORT)
|
|
TOKEN_DEF(ENTITY_CONTAINER)
|
|
TOKEN_DEF(EDITOR_PROPERTY)
|
|
TOKEN_DEF(STARTUP_SCENE)
|
|
TOKEN_DEF(DEBUG_STARTUP_SCENE)
|
|
TOKEN_DEF_END
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::LoadBuffer(byte *Buffer, bool Complete) {
|
|
TOKEN_TABLE_START(commands)
|
|
TOKEN_TABLE(GAME)
|
|
TOKEN_TABLE(AD_GAME)
|
|
TOKEN_TABLE(RESPONSE_BOX)
|
|
TOKEN_TABLE(INVENTORY_BOX)
|
|
TOKEN_TABLE(ITEMS)
|
|
TOKEN_TABLE(TALK_SKIP_BUTTON)
|
|
TOKEN_TABLE(SCENE_VIEWPORT)
|
|
TOKEN_TABLE(EDITOR_PROPERTY)
|
|
TOKEN_TABLE(STARTUP_SCENE)
|
|
TOKEN_TABLE(DEBUG_STARTUP_SCENE)
|
|
TOKEN_TABLE_END
|
|
|
|
byte *params;
|
|
byte *params2;
|
|
int cmd = 1;
|
|
CBParser parser(Game);
|
|
|
|
bool ItemFound = false, ItemsFound = false;
|
|
|
|
while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) {
|
|
switch (cmd) {
|
|
case TOKEN_GAME:
|
|
if (FAILED(CBGame::LoadBuffer(params, false))) cmd = PARSERR_GENERIC;
|
|
break;
|
|
|
|
case TOKEN_AD_GAME:
|
|
while (cmd > 0 && (cmd = parser.GetCommand((char **)¶ms, commands, (char **)¶ms2)) > 0) {
|
|
switch (cmd) {
|
|
case TOKEN_RESPONSE_BOX:
|
|
delete _responseBox;
|
|
_responseBox = new CAdResponseBox(Game);
|
|
if (_responseBox && !FAILED(_responseBox->LoadFile((char *)params2)))
|
|
RegisterObject(_responseBox);
|
|
else {
|
|
delete _responseBox;
|
|
_responseBox = NULL;
|
|
cmd = PARSERR_GENERIC;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_INVENTORY_BOX:
|
|
delete _inventoryBox;
|
|
_inventoryBox = new CAdInventoryBox(Game);
|
|
if (_inventoryBox && !FAILED(_inventoryBox->LoadFile((char *)params2)))
|
|
RegisterObject(_inventoryBox);
|
|
else {
|
|
delete _inventoryBox;
|
|
_inventoryBox = NULL;
|
|
cmd = PARSERR_GENERIC;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_ITEMS:
|
|
ItemsFound = true;
|
|
CBUtils::SetString(&_itemsFile, (char *)params2);
|
|
if (FAILED(LoadItemsFile(_itemsFile))) {
|
|
delete[] _itemsFile;
|
|
_itemsFile = NULL;
|
|
cmd = PARSERR_GENERIC;
|
|
}
|
|
break;
|
|
|
|
case TOKEN_TALK_SKIP_BUTTON:
|
|
if (scumm_stricmp((char *)params2, "right") == 0) _talkSkipButton = TALK_SKIP_RIGHT;
|
|
else if (scumm_stricmp((char *)params2, "both") == 0) _talkSkipButton = TALK_SKIP_BOTH;
|
|
else _talkSkipButton = TALK_SKIP_LEFT;
|
|
break;
|
|
|
|
case TOKEN_SCENE_VIEWPORT: {
|
|
RECT rc;
|
|
parser.ScanStr((char *)params2, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom);
|
|
if (!_sceneViewport) _sceneViewport = new CBViewport(Game);
|
|
if (_sceneViewport) _sceneViewport->SetRect(rc.left, rc.top, rc.right, rc.bottom);
|
|
}
|
|
break;
|
|
|
|
case TOKEN_EDITOR_PROPERTY:
|
|
ParseEditorProperty(params2, false);
|
|
break;
|
|
|
|
case TOKEN_STARTUP_SCENE:
|
|
CBUtils::SetString(&_startupScene, (char *)params2);
|
|
break;
|
|
|
|
case TOKEN_DEBUG_STARTUP_SCENE:
|
|
CBUtils::SetString(&_debugStartupScene, (char *)params2);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cmd == PARSERR_TOKENNOTFOUND) {
|
|
Game->LOG(0, "Syntax error in GAME definition");
|
|
return E_FAIL;
|
|
}
|
|
if (cmd == PARSERR_GENERIC) {
|
|
Game->LOG(0, "Error loading GAME definition");
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (ItemFound && !ItemsFound) {
|
|
Game->LOG(0, "**Warning** Please put the items definition to a separate file.");
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::Persist(CBPersistMgr *PersistMgr) {
|
|
if (!PersistMgr->_saving) Cleanup();
|
|
CBGame::Persist(PersistMgr);
|
|
|
|
_dlgPendingBranches.Persist(PersistMgr);
|
|
|
|
_inventories.Persist(PersistMgr);
|
|
PersistMgr->Transfer(TMEMBER(_inventoryBox));
|
|
|
|
_objects.Persist(PersistMgr);
|
|
|
|
PersistMgr->Transfer(TMEMBER(_prevSceneName));
|
|
PersistMgr->Transfer(TMEMBER(_prevSceneFilename));
|
|
|
|
PersistMgr->Transfer(TMEMBER(_responseBox));
|
|
_responsesBranch.Persist(PersistMgr);
|
|
_responsesGame.Persist(PersistMgr);
|
|
PersistMgr->Transfer(TMEMBER(_scene));
|
|
_sceneStates.Persist(PersistMgr);
|
|
PersistMgr->Transfer(TMEMBER(_scheduledFadeIn));
|
|
PersistMgr->Transfer(TMEMBER(_scheduledScene));
|
|
PersistMgr->Transfer(TMEMBER(_selectedItem));
|
|
PersistMgr->Transfer(TMEMBER_INT(_talkSkipButton));
|
|
|
|
_sentences.Persist(PersistMgr);
|
|
|
|
PersistMgr->Transfer(TMEMBER(_sceneViewport));
|
|
PersistMgr->Transfer(TMEMBER_INT(_stateEx));
|
|
PersistMgr->Transfer(TMEMBER(_initialScene));
|
|
PersistMgr->Transfer(TMEMBER(_debugStartupScene));
|
|
|
|
PersistMgr->Transfer(TMEMBER(_invObject));
|
|
PersistMgr->Transfer(TMEMBER(_inventoryOwner));
|
|
PersistMgr->Transfer(TMEMBER(_tempDisableSaveState));
|
|
_items.Persist(PersistMgr);
|
|
|
|
PersistMgr->Transfer(TMEMBER(_itemsFile));
|
|
|
|
_speechDirs.Persist(PersistMgr);
|
|
PersistMgr->Transfer(TMEMBER(_smartItemCursor));
|
|
|
|
if (!PersistMgr->_saving) _initialScene = false;
|
|
|
|
PersistMgr->Transfer(TMEMBER(_startupScene));
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::LoadGame(const char *Filename) {
|
|
HRESULT ret = CBGame::LoadGame(Filename);
|
|
if (SUCCEEDED(ret)) CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadRegion, "CAdRegion", NULL);
|
|
return ret;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::InitAfterLoad() {
|
|
CBGame::InitAfterLoad();
|
|
CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadScene, "CAdScene", NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::AfterLoadScene(void *Scene, void *Data) {
|
|
((CAdScene *)Scene)->AfterLoad();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::SetPrevSceneName(const char *Name) {
|
|
delete[] _prevSceneName;
|
|
_prevSceneName = NULL;
|
|
if (Name) {
|
|
_prevSceneName = new char[strlen(Name) + 1];
|
|
if (_prevSceneName) strcpy(_prevSceneName, Name);
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdGame::SetPrevSceneFilename(const char *Name) {
|
|
delete[] _prevSceneFilename;
|
|
_prevSceneFilename = NULL;
|
|
if (Name) {
|
|
_prevSceneFilename = new char[strlen(Name) + 1];
|
|
if (_prevSceneFilename) strcpy(_prevSceneFilename, Name);
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ScheduleChangeScene(const char *Filename, bool FadeIn) {
|
|
delete[] _scheduledScene;
|
|
_scheduledScene = NULL;
|
|
|
|
if (_scene && !_scene->_initialized) return ChangeScene(Filename, FadeIn);
|
|
else {
|
|
_scheduledScene = new char [strlen(Filename) + 1];
|
|
strcpy(_scheduledScene, Filename);
|
|
|
|
_scheduledFadeIn = FadeIn;
|
|
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::GetVersion(byte *VerMajor, byte *VerMinor, byte *ExtMajor, byte *ExtMinor) {
|
|
CBGame::GetVersion(VerMajor, VerMinor, NULL, NULL);
|
|
|
|
if (ExtMajor) *ExtMajor = 0;
|
|
if (ExtMinor) *ExtMinor = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::LoadItemsFile(const char *Filename, bool Merge) {
|
|
byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
|
|
if (Buffer == NULL) {
|
|
Game->LOG(0, "CAdGame::LoadItemsFile failed for file '%s'", Filename);
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT ret;
|
|
|
|
//_filename = new char [strlen(Filename)+1];
|
|
//strcpy(_filename, Filename);
|
|
|
|
if (FAILED(ret = LoadItemsBuffer(Buffer, Merge))) Game->LOG(0, "Error parsing ITEMS file '%s'", Filename);
|
|
|
|
|
|
delete [] Buffer;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::LoadItemsBuffer(byte *Buffer, bool Merge) {
|
|
TOKEN_TABLE_START(commands)
|
|
TOKEN_TABLE(ITEM)
|
|
TOKEN_TABLE_END
|
|
|
|
byte *params;
|
|
int cmd;
|
|
CBParser parser(Game);
|
|
|
|
if (!Merge) {
|
|
while (_items.GetSize() > 0) DeleteItem(_items[0]);
|
|
}
|
|
|
|
while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) {
|
|
switch (cmd) {
|
|
case TOKEN_ITEM: {
|
|
CAdItem *item = new CAdItem(Game);
|
|
if (item && !FAILED(item->LoadBuffer(params, false))) {
|
|
// delete item with the same name, if exists
|
|
if (Merge) {
|
|
CAdItem *PrevItem = GetItemByName(item->_name);
|
|
if (PrevItem) DeleteItem(PrevItem);
|
|
}
|
|
AddItem(item);
|
|
} else {
|
|
delete item;
|
|
item = NULL;
|
|
cmd = PARSERR_GENERIC;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (cmd == PARSERR_TOKENNOTFOUND) {
|
|
Game->LOG(0, "Syntax error in ITEMS definition");
|
|
return E_FAIL;
|
|
}
|
|
if (cmd == PARSERR_GENERIC) {
|
|
Game->LOG(0, "Error loading ITEMS definition");
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdSceneState *CAdGame::GetSceneState(const char *Filename, bool Saving) {
|
|
char *FilenameCor = new char[strlen(Filename) + 1];
|
|
strcpy(FilenameCor, Filename);
|
|
for (int i = 0; i < strlen(FilenameCor); i++) {
|
|
if (FilenameCor[i] == '/') FilenameCor[i] = '\\';
|
|
}
|
|
|
|
for (int i = 0; i < _sceneStates.GetSize(); i++) {
|
|
if (scumm_stricmp(_sceneStates[i]->_filename, FilenameCor) == 0) {
|
|
delete [] FilenameCor;
|
|
return _sceneStates[i];
|
|
}
|
|
}
|
|
|
|
if (Saving) {
|
|
CAdSceneState *ret = new CAdSceneState(Game);
|
|
ret->SetFilename(FilenameCor);
|
|
|
|
_sceneStates.Add(ret);
|
|
|
|
delete [] FilenameCor;
|
|
return ret;
|
|
} else {
|
|
delete [] FilenameCor;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::WindowLoadHook(CUIWindow *Win, char **Buffer, char **params) {
|
|
TOKEN_TABLE_START(commands)
|
|
TOKEN_TABLE(ENTITY_CONTAINER)
|
|
TOKEN_TABLE_END
|
|
|
|
int cmd = PARSERR_GENERIC;
|
|
CBParser parser(Game);
|
|
|
|
cmd = parser.GetCommand(Buffer, commands, params);
|
|
switch (cmd) {
|
|
case TOKEN_ENTITY_CONTAINER: {
|
|
CUIEntity *ent = new CUIEntity(Game);
|
|
if (!ent || FAILED(ent->LoadBuffer((byte *)*params, false))) {
|
|
delete ent;
|
|
ent = NULL;
|
|
cmd = PARSERR_GENERIC;
|
|
} else {
|
|
ent->_parent = Win;
|
|
Win->_widgets.Add(ent);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (cmd == PARSERR_TOKENNOTFOUND || cmd == PARSERR_GENERIC) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::WindowScriptMethodHook(CUIWindow *Win, CScScript *Script, CScStack *Stack, const char *Name) {
|
|
if (strcmp(Name, "CreateEntityContainer") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CUIEntity *Ent = new CUIEntity(Game);
|
|
if (!Val->IsNULL()) Ent->SetName(Val->GetString());
|
|
Stack->PushNative(Ent, true);
|
|
|
|
Ent->_parent = Win;
|
|
Win->_widgets.Add(Ent);
|
|
|
|
return S_OK;
|
|
} else return E_FAIL;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::StartDlgBranch(const char *BranchName, const char *ScriptName, const char *EventName) {
|
|
char *Name = new char[strlen(BranchName) + 1 + strlen(ScriptName) + 1 + strlen(EventName) + 1];
|
|
if (Name) {
|
|
sprintf(Name, "%s.%s.%s", BranchName, ScriptName, EventName);
|
|
_dlgPendingBranches.Add(Name);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::EndDlgBranch(const char *BranchName, const char *ScriptName, const char *EventName) {
|
|
char *Name = NULL;
|
|
bool DeleteName = false;
|
|
if (BranchName == NULL && _dlgPendingBranches.GetSize() > 0) {
|
|
Name = _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1];
|
|
} else {
|
|
if (BranchName != NULL) {
|
|
Name = new char[strlen(BranchName) + 1 + strlen(ScriptName) + 1 + strlen(EventName) + 1];
|
|
if (Name) {
|
|
sprintf(Name, "%s.%s.%s", BranchName, ScriptName, EventName);
|
|
DeleteName = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Name == NULL) return S_OK;
|
|
|
|
|
|
int StartIndex = -1;
|
|
int i;
|
|
for (i = _dlgPendingBranches.GetSize() - 1; i >= 0; i--) {
|
|
if (scumm_stricmp(Name, _dlgPendingBranches[i]) == 0) {
|
|
StartIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
if (StartIndex >= 0) {
|
|
for (i = StartIndex; i < _dlgPendingBranches.GetSize(); i++) {
|
|
//ClearBranchResponses(_dlgPendingBranches[i]);
|
|
delete [] _dlgPendingBranches[i];
|
|
_dlgPendingBranches[i] = NULL;
|
|
}
|
|
_dlgPendingBranches.RemoveAt(StartIndex, _dlgPendingBranches.GetSize() - StartIndex);
|
|
}
|
|
|
|
// dialogue is over, forget selected responses
|
|
if (_dlgPendingBranches.GetSize() == 0) {
|
|
for (int i = 0; i < _responsesBranch.GetSize(); i++) delete _responsesBranch[i];
|
|
_responsesBranch.RemoveAll();
|
|
}
|
|
|
|
if (DeleteName) delete [] Name;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ClearBranchResponses(char *Name) {
|
|
for (int i = 0; i < _responsesBranch.GetSize(); i++) {
|
|
if (scumm_stricmp(Name, _responsesBranch[i]->_context) == 0) {
|
|
delete _responsesBranch[i];
|
|
_responsesBranch.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::AddBranchResponse(int ID) {
|
|
if (BranchResponseUsed(ID)) return S_OK;
|
|
CAdResponseContext *r = new CAdResponseContext(Game);
|
|
r->_iD = ID;
|
|
r->SetContext(_dlgPendingBranches.GetSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1] : NULL);
|
|
_responsesBranch.Add(r);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAdGame::BranchResponseUsed(int ID) {
|
|
char *Context = _dlgPendingBranches.GetSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1] : NULL;
|
|
for (int i = 0; i < _responsesBranch.GetSize(); i++) {
|
|
if (_responsesBranch[i]->_iD == ID) {
|
|
if ((Context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(Context, _responsesBranch[i]->_context) == 0) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::AddGameResponse(int ID) {
|
|
if (GameResponseUsed(ID)) return S_OK;
|
|
CAdResponseContext *r = new CAdResponseContext(Game);
|
|
r->_iD = ID;
|
|
r->SetContext(_dlgPendingBranches.GetSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1] : NULL);
|
|
_responsesGame.Add(r);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAdGame::GameResponseUsed(int ID) {
|
|
char *Context = _dlgPendingBranches.GetSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1] : NULL;
|
|
for (int i = 0; i < _responsesGame.GetSize(); i++) {
|
|
CAdResponseContext *RespContext = _responsesGame[i];
|
|
if (RespContext->_iD == ID) {
|
|
if ((Context == NULL && RespContext->_context == NULL) || ((Context != NULL && RespContext->_context != NULL) && scumm_stricmp(Context, RespContext->_context) == 0)) return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ResetResponse(int ID) {
|
|
char *Context = _dlgPendingBranches.GetSize() > 0 ? _dlgPendingBranches[_dlgPendingBranches.GetSize() - 1] : NULL;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < _responsesGame.GetSize(); i++) {
|
|
if (_responsesGame[i]->_iD == ID) {
|
|
if ((Context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(Context, _responsesGame[i]->_context) == 0) {
|
|
delete _responsesGame[i];
|
|
_responsesGame.RemoveAt(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < _responsesBranch.GetSize(); i++) {
|
|
if (_responsesBranch[i]->_iD == ID) {
|
|
if ((Context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(Context, _responsesBranch[i]->_context) == 0) {
|
|
delete _responsesBranch[i];
|
|
_responsesBranch.RemoveAt(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::DisplayContent(bool Update, bool DisplayAll) {
|
|
// init
|
|
if (Update) InitLoop();
|
|
|
|
// fill black
|
|
_renderer->Fill(0, 0, 0);
|
|
if (!_editorMode) _renderer->SetScreenViewport();
|
|
|
|
// process scripts
|
|
if (Update) _scEngine->Tick();
|
|
|
|
POINT p;
|
|
GetMousePos(&p);
|
|
|
|
_scene->Update();
|
|
_scene->Display();
|
|
|
|
|
|
// display in-game windows
|
|
DisplayWindows(true);
|
|
if (_inventoryBox) _inventoryBox->Display();
|
|
if (_stateEx == GAME_WAITING_RESPONSE) _responseBox->Display();
|
|
if (_indicatorDisplay) DisplayIndicator();
|
|
|
|
|
|
if (Update || DisplayAll) {
|
|
// display normal windows
|
|
DisplayWindows(false);
|
|
|
|
SetActiveObject(Game->_renderer->GetObjectAt(p.x, p.y));
|
|
|
|
// textual info
|
|
DisplaySentences(_state == GAME_FROZEN);
|
|
|
|
ShowCursor();
|
|
|
|
if (_fader) _fader->Display();
|
|
_transMgr->Update();
|
|
}
|
|
|
|
|
|
if (_loadingIcon) {
|
|
_loadingIcon->Display(_loadingIconX, _loadingIconY);
|
|
if (!_loadingIconPersistent) {
|
|
delete _loadingIcon;
|
|
_loadingIcon = NULL;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::RegisterInventory(CAdInventory *Inv) {
|
|
for (int i = 0; i < _inventories.GetSize(); i++) {
|
|
if (_inventories[i] == Inv) return S_OK;
|
|
}
|
|
RegisterObject(Inv);
|
|
_inventories.Add(Inv);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::UnregisterInventory(CAdInventory *Inv) {
|
|
for (int i = 0; i < _inventories.GetSize(); i++) {
|
|
if (_inventories[i] == Inv) {
|
|
UnregisterObject(_inventories[i]);
|
|
_inventories.RemoveAt(i);
|
|
return S_OK;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAdGame::IsItemTaken(char *ItemName) {
|
|
int i;
|
|
|
|
for (i = 0; i < _inventories.GetSize(); i++) {
|
|
CAdInventory *Inv = _inventories[i];
|
|
|
|
for (int j = 0; j < Inv->_takenItems.GetSize(); j++) {
|
|
if (scumm_stricmp(ItemName, Inv->_takenItems[j]->_name) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdItem *CAdGame::GetItemByName(const char *Name) {
|
|
for (int i = 0; i < _items.GetSize(); i++) {
|
|
if (scumm_stricmp(_items[i]->_name, Name) == 0) return _items[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::AddItem(CAdItem *Item) {
|
|
_items.Add(Item);
|
|
return Game->RegisterObject(Item);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::ResetContent() {
|
|
int i;
|
|
|
|
// clear pending dialogs
|
|
for (i = 0; i < _dlgPendingBranches.GetSize(); i++) {
|
|
delete [] _dlgPendingBranches[i];
|
|
}
|
|
_dlgPendingBranches.RemoveAll();
|
|
|
|
|
|
// clear inventories
|
|
for (i = 0; i < _inventories.GetSize(); i++) {
|
|
_inventories[i]->_takenItems.RemoveAll();
|
|
}
|
|
|
|
// clear scene states
|
|
for (i = 0; i < _sceneStates.GetSize(); i++) delete _sceneStates[i];
|
|
_sceneStates.RemoveAll();
|
|
|
|
// clear once responses
|
|
for (i = 0; i < _responsesBranch.GetSize(); i++) delete _responsesBranch[i];
|
|
_responsesBranch.RemoveAll();
|
|
|
|
// clear once game responses
|
|
for (i = 0; i < _responsesGame.GetSize(); i++) delete _responsesGame[i];
|
|
_responsesGame.RemoveAll();
|
|
|
|
// reload inventory items
|
|
if (_itemsFile) LoadItemsFile(_itemsFile);
|
|
|
|
_tempDisableSaveState = true;
|
|
|
|
return CBGame::ResetContent();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::DeleteItem(CAdItem *Item) {
|
|
if (!Item) return E_FAIL;
|
|
|
|
if (_selectedItem == Item) _selectedItem = NULL;
|
|
_scene->HandleItemAssociations(Item->_name, false);
|
|
|
|
// remove from all inventories
|
|
for (int i = 0; i < _inventories.GetSize(); i++) {
|
|
_inventories[i]->RemoveItem(Item);
|
|
}
|
|
|
|
// remove object
|
|
for (int i = 0; i < _items.GetSize(); i++) {
|
|
if (_items[i] == Item) {
|
|
UnregisterObject(_items[i]);
|
|
_items.RemoveAt(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::AddSpeechDir(const char *Dir) {
|
|
if (!Dir || Dir[0] == '\0') return E_FAIL;
|
|
|
|
char *Temp = new char[strlen(Dir) + 2];
|
|
strcpy(Temp, Dir);
|
|
if (Temp[strlen(Temp) - 1] != '\\' && Temp[strlen(Temp) - 1] != '/')
|
|
strcat(Temp, "\\");
|
|
|
|
for (int i = 0; i < _speechDirs.GetSize(); i++) {
|
|
if (scumm_stricmp(_speechDirs[i], Temp) == 0) {
|
|
delete [] Temp;
|
|
return S_OK;
|
|
}
|
|
}
|
|
_speechDirs.Add(Temp);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::RemoveSpeechDir(const char *Dir) {
|
|
if (!Dir || Dir[0] == '\0') return E_FAIL;
|
|
|
|
char *Temp = new char[strlen(Dir) + 2];
|
|
strcpy(Temp, Dir);
|
|
if (Temp[strlen(Temp) - 1] != '\\' && Temp[strlen(Temp) - 1] != '/')
|
|
strcat(Temp, "\\");
|
|
|
|
bool Found = false;
|
|
for (int i = 0; i < _speechDirs.GetSize(); i++) {
|
|
if (scumm_stricmp(_speechDirs[i], Temp) == 0) {
|
|
delete [] _speechDirs[i];
|
|
_speechDirs.RemoveAt(i);
|
|
Found = true;
|
|
break;
|
|
}
|
|
}
|
|
delete [] Temp;
|
|
|
|
if (Found) return S_OK;
|
|
else return E_FAIL;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
char *CAdGame::FindSpeechFile(char *StringID) {
|
|
char *Ret = new char[MAX_PATH];
|
|
|
|
for (int i = 0; i < _speechDirs.GetSize(); i++) {
|
|
sprintf(Ret, "%s%s.ogg", _speechDirs[i], StringID);
|
|
CBFile *File = _fileManager->OpenFile(Ret);
|
|
if (File) {
|
|
_fileManager->CloseFile(File);
|
|
return Ret;
|
|
}
|
|
|
|
sprintf(Ret, "%s%s.wav", _speechDirs[i], StringID);
|
|
File = _fileManager->OpenFile(Ret);
|
|
if (File) {
|
|
_fileManager->CloseFile(File);
|
|
return Ret;
|
|
}
|
|
}
|
|
delete [] Ret;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAdGame::ValidMouse() {
|
|
POINT Pos;
|
|
CBPlatform::GetCursorPos(&Pos);
|
|
|
|
return _renderer->PointInViewport(&Pos);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnMouseLeftDown() {
|
|
if (!ValidMouse()) return S_OK;
|
|
if (_state == GAME_RUNNING && !_interactive) {
|
|
if (_talkSkipButton == TALK_SKIP_LEFT || _talkSkipButton == TALK_SKIP_BOTH) {
|
|
FinishSentences();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
if (_activeObject) _activeObject->HandleMouse(MOUSE_CLICK, MOUSE_BUTTON_LEFT);
|
|
|
|
bool Handled = _state == GAME_RUNNING && SUCCEEDED(ApplyEvent("LeftClick"));
|
|
if (!Handled) {
|
|
if (_activeObject != NULL) {
|
|
_activeObject->ApplyEvent("LeftClick");
|
|
} else if (_state == GAME_RUNNING && _scene && _scene->PointInViewport(_mousePos.x, _mousePos.y)) {
|
|
_scene->ApplyEvent("LeftClick");
|
|
}
|
|
}
|
|
|
|
if (_activeObject != NULL) Game->_capturedObject = Game->_activeObject;
|
|
_mouseLeftDown = true;
|
|
CBPlatform::SetCapture(_renderer->_window);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnMouseLeftUp() {
|
|
if (_activeObject) _activeObject->HandleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT);
|
|
|
|
CBPlatform::ReleaseCapture();
|
|
_capturedObject = NULL;
|
|
_mouseLeftDown = false;
|
|
|
|
bool Handled = /*_state==GAME_RUNNING &&*/ SUCCEEDED(ApplyEvent("LeftRelease"));
|
|
if (!Handled) {
|
|
if (_activeObject != NULL) {
|
|
_activeObject->ApplyEvent("LeftRelease");
|
|
} else if (_state == GAME_RUNNING && _scene && _scene->PointInViewport(_mousePos.x, _mousePos.y)) {
|
|
_scene->ApplyEvent("LeftRelease");
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnMouseLeftDblClick() {
|
|
if (!ValidMouse()) return S_OK;
|
|
|
|
if (_state == GAME_RUNNING && !_interactive) return S_OK;
|
|
|
|
if (_activeObject) _activeObject->HandleMouse(MOUSE_DBLCLICK, MOUSE_BUTTON_LEFT);
|
|
|
|
bool Handled = _state == GAME_RUNNING && SUCCEEDED(ApplyEvent("LeftDoubleClick"));
|
|
if (!Handled) {
|
|
if (_activeObject != NULL) {
|
|
_activeObject->ApplyEvent("LeftDoubleClick");
|
|
} else if (_state == GAME_RUNNING && _scene && _scene->PointInViewport(_mousePos.x, _mousePos.y)) {
|
|
_scene->ApplyEvent("LeftDoubleClick");
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnMouseRightDown() {
|
|
if (!ValidMouse()) return S_OK;
|
|
if (_state == GAME_RUNNING && !_interactive) {
|
|
if (_talkSkipButton == TALK_SKIP_RIGHT || _talkSkipButton == TALK_SKIP_BOTH) {
|
|
FinishSentences();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
if ((_state == GAME_RUNNING && !_interactive) || _stateEx == GAME_WAITING_RESPONSE) return S_OK;
|
|
|
|
if (_activeObject) _activeObject->HandleMouse(MOUSE_CLICK, MOUSE_BUTTON_RIGHT);
|
|
|
|
bool Handled = _state == GAME_RUNNING && SUCCEEDED(ApplyEvent("RightClick"));
|
|
if (!Handled) {
|
|
if (_activeObject != NULL) {
|
|
_activeObject->ApplyEvent("RightClick");
|
|
} else if (_state == GAME_RUNNING && _scene && _scene->PointInViewport(_mousePos.x, _mousePos.y)) {
|
|
_scene->ApplyEvent("RightClick");
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnMouseRightUp() {
|
|
if (_activeObject) _activeObject->HandleMouse(MOUSE_RELEASE, MOUSE_BUTTON_RIGHT);
|
|
|
|
bool Handled = _state == GAME_RUNNING && SUCCEEDED(ApplyEvent("RightRelease"));
|
|
if (!Handled) {
|
|
if (_activeObject != NULL) {
|
|
_activeObject->ApplyEvent("RightRelease");
|
|
} else if (_state == GAME_RUNNING && _scene && _scene->PointInViewport(_mousePos.x, _mousePos.y)) {
|
|
_scene->ApplyEvent("RightRelease");
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::DisplayDebugInfo() {
|
|
char str[100];
|
|
if (Game->_dEBUG_DebugMode) {
|
|
sprintf(str, "Mouse: %d, %d (scene: %d, %d)", _mousePos.x, _mousePos.y, _mousePos.x + _scene->GetOffsetLeft(), _mousePos.y + _scene->GetOffsetTop());
|
|
_systemFont->DrawText((byte *)str, 0, 90, _renderer->_width, TAL_RIGHT);
|
|
|
|
sprintf(str, "Scene: %s (prev: %s)", (_scene && _scene->_name) ? _scene->_name : "???", _prevSceneName ? _prevSceneName : "???");
|
|
_systemFont->DrawText((byte *)str, 0, 110, _renderer->_width, TAL_RIGHT);
|
|
}
|
|
return CBGame::DisplayDebugInfo();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdGame::OnScriptShutdown(CScScript *Script) {
|
|
if (_responseBox && _responseBox->_waitingScript == Script)
|
|
_responseBox->_waitingScript = NULL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
} // end of namespace WinterMute
|