mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 01:39:57 +00:00
1192 lines
37 KiB
C++
1192 lines
37 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 "dcgf.h"
|
|
#include "engines/wintermute/AdGame.h"
|
|
#include "engines/wintermute/AdItem.h"
|
|
#include "engines/wintermute/AdObject.h"
|
|
#include "engines/wintermute/AdInventory.h"
|
|
#include "engines/wintermute/AdLayer.h"
|
|
#include "engines/wintermute/AdScene.h"
|
|
#include "engines/wintermute/AdSceneNode.h"
|
|
#include "engines/wintermute/AdSentence.h"
|
|
#include "engines/wintermute/AdWaypointGroup.h"
|
|
#include "engines/wintermute/BGame.h"
|
|
#include "engines/wintermute/BFrame.h"
|
|
#include "engines/wintermute/BSound.h"
|
|
#include "engines/wintermute/BSurfaceStorage.h"
|
|
#include "engines/wintermute/BSubFrame.h"
|
|
#include "engines/wintermute/BFont.h"
|
|
#include "engines/wintermute/BFontStorage.h"
|
|
#include "engines/wintermute/BSprite.h"
|
|
#include "engines/wintermute/BStringTable.h"
|
|
#include "engines/wintermute/scriptables/ScEngine.h"
|
|
#include "engines/wintermute/scriptables/ScScript.h"
|
|
#include "engines/wintermute/scriptables/ScStack.h"
|
|
#include "engines/wintermute/scriptables/ScValue.h"
|
|
#include "common/str.h"
|
|
#include "common/util.h"
|
|
|
|
namespace WinterMute {
|
|
|
|
IMPLEMENT_PERSISTENT(CAdObject, false)
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdObject::CAdObject(CBGame *inGame): CBObject(inGame) {
|
|
m_Type = OBJECT_NONE;
|
|
m_State = m_NextState = STATE_NONE;
|
|
|
|
m_Active = true;
|
|
m_Drawn = false;
|
|
|
|
m_CurrentSprite = NULL;
|
|
m_AnimSprite = NULL;
|
|
m_TempSprite2 = NULL;
|
|
|
|
m_Font = NULL;
|
|
|
|
m_Sentence = NULL;
|
|
|
|
m_ForcedTalkAnimName = NULL;
|
|
m_ForcedTalkAnimUsed = false;
|
|
|
|
m_BlockRegion = NULL;
|
|
m_WptGroup = NULL;
|
|
|
|
m_CurrentBlockRegion = NULL;
|
|
m_CurrentWptGroup = NULL;
|
|
|
|
m_IgnoreItems = false;
|
|
m_SceneIndependent = false;
|
|
|
|
m_StickRegion = NULL;
|
|
|
|
m_SubtitlesModRelative = true;
|
|
m_SubtitlesModX = 0;
|
|
m_SubtitlesModY = 0;
|
|
m_SubtitlesWidth = 0;
|
|
m_SubtitlesModXCenter = true;
|
|
|
|
m_Inventory = NULL;
|
|
|
|
for (int i = 0; i < MAX_NUM_REGIONS; i++) m_CurrentRegions[i] = NULL;
|
|
|
|
m_PartEmitter = NULL;
|
|
m_PartFollowParent = false;
|
|
m_PartOffsetX = m_PartOffsetY = 0;
|
|
|
|
m_RegisterAlias = this;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdObject::~CAdObject() {
|
|
m_CurrentSprite = NULL; // reference only, don't delete
|
|
SAFE_DELETE(m_AnimSprite);
|
|
SAFE_DELETE(m_Sentence);
|
|
SAFE_DELETE_ARRAY(m_ForcedTalkAnimName);
|
|
|
|
SAFE_DELETE(m_BlockRegion);
|
|
SAFE_DELETE(m_WptGroup);
|
|
|
|
SAFE_DELETE(m_CurrentBlockRegion);
|
|
SAFE_DELETE(m_CurrentWptGroup);
|
|
|
|
|
|
m_TempSprite2 = NULL; // reference only
|
|
m_StickRegion = NULL;
|
|
|
|
if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
|
|
|
|
if (m_Inventory) {
|
|
((CAdGame *)Game)->UnregisterInventory(m_Inventory);
|
|
m_Inventory = NULL;
|
|
}
|
|
|
|
if (m_PartEmitter)
|
|
Game->UnregisterObject(m_PartEmitter);
|
|
|
|
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
Game->UnregisterObject(m_AttachmentsPre[i]);
|
|
}
|
|
m_AttachmentsPre.RemoveAll();
|
|
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
Game->UnregisterObject(m_AttachmentsPost[i]);
|
|
}
|
|
m_AttachmentsPost.RemoveAll();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::PlayAnim(char *Filename) {
|
|
SAFE_DELETE(m_AnimSprite);
|
|
m_AnimSprite = new CBSprite(Game, this);
|
|
if (!m_AnimSprite) {
|
|
Game->LOG(0, "CAdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", m_Name, Filename);
|
|
return E_FAIL;
|
|
}
|
|
HRESULT res = m_AnimSprite->LoadFile(Filename);
|
|
if (FAILED(res)) {
|
|
Game->LOG(res, "CAdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", m_Name, Filename);
|
|
SAFE_DELETE(m_AnimSprite);
|
|
return res;
|
|
}
|
|
m_State = STATE_PLAYING_ANIM;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::Display() {
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::Update() {
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// high level scripting interface
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) {
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PlayAnim / PlayAnimAsync
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "PlayAnim") == 0 || strcmp(Name, "PlayAnimAsync") == 0) {
|
|
Stack->CorrectParams(1);
|
|
if (FAILED(PlayAnim(Stack->Pop()->GetString()))) Stack->PushBool(false);
|
|
else {
|
|
if (strcmp(Name, "PlayAnimAsync") != 0) Script->WaitFor(this);
|
|
Stack->PushBool(true);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Reset
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "Reset") == 0) {
|
|
Stack->CorrectParams(0);
|
|
Reset();
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// IsTalking
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "IsTalking") == 0) {
|
|
Stack->CorrectParams(0);
|
|
Stack->PushBool(m_State == STATE_TALKING);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// StopTalk / StopTalking
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "StopTalk") == 0 || strcmp(Name, "StopTalking") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (m_Sentence) m_Sentence->Finish();
|
|
if (m_State == STATE_TALKING) {
|
|
m_State = m_NextState;
|
|
m_NextState = STATE_READY;
|
|
Stack->PushBool(true);
|
|
} else Stack->PushBool(false);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ForceTalkAnim
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ForceTalkAnim") == 0) {
|
|
Stack->CorrectParams(1);
|
|
char *AnimName = Stack->Pop()->GetString();
|
|
SAFE_DELETE_ARRAY(m_ForcedTalkAnimName);
|
|
m_ForcedTalkAnimName = new char[strlen(AnimName) + 1];
|
|
strcpy(m_ForcedTalkAnimName, AnimName);
|
|
m_ForcedTalkAnimUsed = false;
|
|
Stack->PushBool(true);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Talk / TalkAsync
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "Talk") == 0 || strcmp(Name, "TalkAsync") == 0) {
|
|
Stack->CorrectParams(5);
|
|
|
|
char *Text = Stack->Pop()->GetString();
|
|
CScValue *SoundVal = Stack->Pop();
|
|
int Duration = Stack->Pop()->GetInt();
|
|
CScValue *ValStances = Stack->Pop();
|
|
|
|
char *Stances = ValStances->IsNULL() ? NULL : ValStances->GetString();
|
|
|
|
int Align;
|
|
CScValue *val = Stack->Pop();
|
|
if (val->IsNULL()) Align = TAL_CENTER;
|
|
else Align = val->GetInt();
|
|
|
|
Align = MIN(MAX(0, Align), NUM_TEXT_ALIGN - 1);
|
|
|
|
char *Sound = SoundVal->IsNULL() ? NULL : SoundVal->GetString();
|
|
|
|
Talk(Text, Sound, Duration, Stances, (TTextAlign)Align);
|
|
if (strcmp(Name, "TalkAsync") != 0) Script->WaitForExclusive(this);
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// StickToRegion
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "StickToRegion") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
CAdLayer *Main = ((CAdGame *)Game)->m_Scene->m_MainLayer;
|
|
bool RegFound = false;
|
|
|
|
int i;
|
|
CScValue *Val = Stack->Pop();
|
|
if (Val->IsNULL() || !Main) {
|
|
m_StickRegion = NULL;
|
|
RegFound = true;
|
|
} else if (Val->IsString()) {
|
|
char *RegionName = Val->GetString();
|
|
for (i = 0; i < Main->m_Nodes.GetSize(); i++) {
|
|
if (Main->m_Nodes[i]->m_Type == OBJECT_REGION && Main->m_Nodes[i]->m_Region->m_Name && scumm_stricmp(Main->m_Nodes[i]->m_Region->m_Name, RegionName) == 0) {
|
|
m_StickRegion = Main->m_Nodes[i]->m_Region;
|
|
RegFound = true;
|
|
break;
|
|
}
|
|
}
|
|
} else if (Val->IsNative()) {
|
|
CBScriptable *Obj = Val->GetNative();
|
|
|
|
for (i = 0; i < Main->m_Nodes.GetSize(); i++) {
|
|
if (Main->m_Nodes[i]->m_Type == OBJECT_REGION && Main->m_Nodes[i]->m_Region == Obj) {
|
|
m_StickRegion = Main->m_Nodes[i]->m_Region;
|
|
RegFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (!RegFound) m_StickRegion = NULL;
|
|
Stack->PushBool(RegFound);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SetFont
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SetFont") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
if (Val->IsNULL()) SetFont(NULL);
|
|
else SetFont(Val->GetString());
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetFont
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetFont") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (m_Font && m_Font->m_Filename) Stack->PushString(m_Font->m_Filename);
|
|
else Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TakeItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "TakeItem") == 0) {
|
|
Stack->CorrectParams(2);
|
|
|
|
if (!m_Inventory) {
|
|
m_Inventory = new CAdInventory(Game);
|
|
((CAdGame *)Game)->RegisterInventory(m_Inventory);
|
|
}
|
|
|
|
CScValue *val = Stack->Pop();
|
|
if (!val->IsNULL()) {
|
|
char *ItemName = val->GetString();
|
|
val = Stack->Pop();
|
|
char *InsertAfter = val->IsNULL() ? NULL : val->GetString();
|
|
if (FAILED(m_Inventory->InsertItem(ItemName, InsertAfter))) Script->RuntimeError("Cannot add item '%s' to inventory", ItemName);
|
|
else {
|
|
// hide associated entities
|
|
((CAdGame *)Game)->m_Scene->HandleItemAssociations(ItemName, false);
|
|
}
|
|
|
|
} else Script->RuntimeError("TakeItem: item name expected");
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DropItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "DropItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
if (!m_Inventory) {
|
|
m_Inventory = new CAdInventory(Game);
|
|
((CAdGame *)Game)->RegisterInventory(m_Inventory);
|
|
}
|
|
|
|
CScValue *val = Stack->Pop();
|
|
if (!val->IsNULL()) {
|
|
if (FAILED(m_Inventory->RemoveItem(val->GetString()))) Script->RuntimeError("Cannot remove item '%s' from inventory", val->GetString());
|
|
else {
|
|
// show associated entities
|
|
((CAdGame *)Game)->m_Scene->HandleItemAssociations(val->GetString(), true);
|
|
}
|
|
} else Script->RuntimeError("DropItem: item name expected");
|
|
|
|
Stack->PushNULL();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
if (!m_Inventory) {
|
|
m_Inventory = new CAdInventory(Game);
|
|
((CAdGame *)Game)->RegisterInventory(m_Inventory);
|
|
}
|
|
|
|
CScValue *val = Stack->Pop();
|
|
if (val->m_Type == VAL_STRING) {
|
|
CAdItem *item = ((CAdGame *)Game)->GetItemByName(val->GetString());
|
|
if (item) Stack->PushNative(item, true);
|
|
else Stack->PushNULL();
|
|
} else if (val->IsNULL() || val->GetInt() < 0 || val->GetInt() >= m_Inventory->m_TakenItems.GetSize())
|
|
Stack->PushNULL();
|
|
else
|
|
Stack->PushNative(m_Inventory->m_TakenItems[val->GetInt()], true);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// HasItem
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "HasItem") == 0) {
|
|
Stack->CorrectParams(1);
|
|
|
|
if (!m_Inventory) {
|
|
m_Inventory = new CAdInventory(Game);
|
|
((CAdGame *)Game)->RegisterInventory(m_Inventory);
|
|
}
|
|
|
|
CScValue *val = Stack->Pop();
|
|
if (!val->IsNULL()) {
|
|
for (int i = 0; i < m_Inventory->m_TakenItems.GetSize(); i++) {
|
|
if (val->GetNative() == m_Inventory->m_TakenItems[i]) {
|
|
Stack->PushBool(true);
|
|
return S_OK;
|
|
} else if (scumm_stricmp(val->GetString(), m_Inventory->m_TakenItems[i]->m_Name) == 0) {
|
|
Stack->PushBool(true);
|
|
return S_OK;
|
|
}
|
|
}
|
|
} else Script->RuntimeError("HasItem: item name expected");
|
|
|
|
Stack->PushBool(false);
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CreateParticleEmitter
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "CreateParticleEmitter") == 0) {
|
|
Stack->CorrectParams(3);
|
|
bool FollowParent = Stack->Pop()->GetBool();
|
|
int OffsetX = Stack->Pop()->GetInt();
|
|
int OffsetY = Stack->Pop()->GetInt();
|
|
|
|
CPartEmitter *Emitter = CreateParticleEmitter(FollowParent, OffsetX, OffsetY);
|
|
if (Emitter) Stack->PushNative(m_PartEmitter, true);
|
|
else Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DeleteParticleEmitter
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "DeleteParticleEmitter") == 0) {
|
|
Stack->CorrectParams(0);
|
|
if (m_PartEmitter) {
|
|
Game->UnregisterObject(m_PartEmitter);
|
|
m_PartEmitter = NULL;
|
|
}
|
|
Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// AddAttachment
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "AddAttachment") == 0) {
|
|
Stack->CorrectParams(4);
|
|
char *Filename = Stack->Pop()->GetString();
|
|
bool PreDisplay = Stack->Pop()->GetBool(true);
|
|
int OffsetX = Stack->Pop()->GetInt();
|
|
int OffsetY = Stack->Pop()->GetInt();
|
|
|
|
HRESULT res;
|
|
CAdEntity *Ent = new CAdEntity(Game);
|
|
if (FAILED(res = Ent->LoadFile(Filename))) {
|
|
SAFE_DELETE(Ent);
|
|
Script->RuntimeError("AddAttachment() failed loading entity '%s'", Filename);
|
|
Stack->PushBool(false);
|
|
} else {
|
|
Game->RegisterObject(Ent);
|
|
|
|
Ent->m_PosX = OffsetX;
|
|
Ent->m_PosY = OffsetY;
|
|
Ent->m_Active = true;
|
|
|
|
if (PreDisplay) m_AttachmentsPre.Add(Ent);
|
|
else m_AttachmentsPost.Add(Ent);
|
|
|
|
Stack->PushBool(true);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// RemoveAttachment
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "RemoveAttachment") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
bool Found = false;
|
|
if (Val->IsNative()) {
|
|
CBScriptable *Obj = Val->GetNative();
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
if (m_AttachmentsPre[i] == Obj) {
|
|
Found = true;
|
|
Game->UnregisterObject(m_AttachmentsPre[i]);
|
|
m_AttachmentsPre.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
if (m_AttachmentsPost[i] == Obj) {
|
|
Found = true;
|
|
Game->UnregisterObject(m_AttachmentsPost[i]);
|
|
m_AttachmentsPost.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
} else {
|
|
char *Name = Val->GetString();
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
if (m_AttachmentsPre[i]->m_Name && scumm_stricmp(m_AttachmentsPre[i]->m_Name, Name) == 0) {
|
|
Found = true;
|
|
Game->UnregisterObject(m_AttachmentsPre[i]);
|
|
m_AttachmentsPre.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
if (m_AttachmentsPost[i]->m_Name && scumm_stricmp(m_AttachmentsPost[i]->m_Name, Name) == 0) {
|
|
Found = true;
|
|
Game->UnregisterObject(m_AttachmentsPost[i]);
|
|
m_AttachmentsPost.RemoveAt(i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
Stack->PushBool(Found);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// GetAttachment
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "GetAttachment") == 0) {
|
|
Stack->CorrectParams(1);
|
|
CScValue *Val = Stack->Pop();
|
|
|
|
CAdObject *Ret = NULL;
|
|
if (Val->IsInt()) {
|
|
int Index = Val->GetInt();
|
|
int CurrIndex = 0;
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
if (CurrIndex == Index) Ret = m_AttachmentsPre[i];
|
|
CurrIndex++;
|
|
}
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
if (CurrIndex == Index) Ret = m_AttachmentsPost[i];
|
|
CurrIndex++;
|
|
}
|
|
} else {
|
|
char *Name = Val->GetString();
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
if (m_AttachmentsPre[i]->m_Name && scumm_stricmp(m_AttachmentsPre[i]->m_Name, Name) == 0) {
|
|
Ret = m_AttachmentsPre[i];
|
|
break;
|
|
}
|
|
}
|
|
if (!Ret) {
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
if (m_AttachmentsPost[i]->m_Name && scumm_stricmp(m_AttachmentsPost[i]->m_Name, Name) == 0) {
|
|
Ret = m_AttachmentsPre[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Ret != NULL) Stack->PushNative(Ret, true);
|
|
else Stack->PushNULL();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CScValue *CAdObject::ScGetProperty(char *Name) {
|
|
m_ScValue->SetNULL();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Type
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "Type") == 0) {
|
|
m_ScValue->SetString("object");
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Active
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "Active") == 0) {
|
|
m_ScValue->SetBool(m_Active);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// IgnoreItems
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "IgnoreItems") == 0) {
|
|
m_ScValue->SetBool(m_IgnoreItems);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SceneIndependent
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SceneIndependent") == 0) {
|
|
m_ScValue->SetBool(m_SceneIndependent);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesWidth
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesWidth") == 0) {
|
|
m_ScValue->SetInt(m_SubtitlesWidth);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosRelative
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosRelative") == 0) {
|
|
m_ScValue->SetBool(m_SubtitlesModRelative);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosX
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosX") == 0) {
|
|
m_ScValue->SetInt(m_SubtitlesModX);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosY
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosY") == 0) {
|
|
m_ScValue->SetInt(m_SubtitlesModY);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosXCenter
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosXCenter") == 0) {
|
|
m_ScValue->SetBool(m_SubtitlesModXCenter);
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// NumItems (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "NumItems") == 0) {
|
|
m_ScValue->SetInt(GetInventory()->m_TakenItems.GetSize());
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ParticleEmitter (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "ParticleEmitter") == 0) {
|
|
if (m_PartEmitter) m_ScValue->SetNative(m_PartEmitter, true);
|
|
else m_ScValue->SetNULL();
|
|
|
|
return m_ScValue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// NumAttachments (RO)
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "NumAttachments") == 0) {
|
|
m_ScValue->SetInt(m_AttachmentsPre.GetSize() + m_AttachmentsPost.GetSize());
|
|
return m_ScValue;
|
|
}
|
|
|
|
|
|
else return CBObject::ScGetProperty(Name);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::ScSetProperty(char *Name, CScValue *Value) {
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Active
|
|
//////////////////////////////////////////////////////////////////////////
|
|
if (strcmp(Name, "Active") == 0) {
|
|
m_Active = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// IgnoreItems
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "IgnoreItems") == 0) {
|
|
m_IgnoreItems = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SceneIndependent
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SceneIndependent") == 0) {
|
|
m_SceneIndependent = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesWidth
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesWidth") == 0) {
|
|
m_SubtitlesWidth = Value->GetInt();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosRelative
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosRelative") == 0) {
|
|
m_SubtitlesModRelative = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosX
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosX") == 0) {
|
|
m_SubtitlesModX = Value->GetInt();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosY
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosY") == 0) {
|
|
m_SubtitlesModY = Value->GetInt();
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// SubtitlesPosXCenter
|
|
//////////////////////////////////////////////////////////////////////////
|
|
else if (strcmp(Name, "SubtitlesPosXCenter") == 0) {
|
|
m_SubtitlesModXCenter = Value->GetBool();
|
|
return S_OK;
|
|
}
|
|
|
|
else return CBObject::ScSetProperty(Name, Value);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
char *CAdObject::ScToString() {
|
|
return "[ad object]";
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::SetFont(char *Filename) {
|
|
if (m_Font) Game->m_FontStorage->RemoveFont(m_Font);
|
|
if (Filename) {
|
|
m_Font = Game->m_FontStorage->AddFont(Filename);
|
|
return m_Font == NULL ? E_FAIL : S_OK;
|
|
} else {
|
|
m_Font = NULL;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CAdObject::GetHeight() {
|
|
if (!m_CurrentSprite) return 0;
|
|
else {
|
|
CBFrame *frame = m_CurrentSprite->m_Frames[m_CurrentSprite->m_CurrentFrame];
|
|
int ret = 0;
|
|
for (int i = 0; i < frame->m_Subframes.GetSize(); i++) {
|
|
ret = MAX(ret, frame->m_Subframes[i]->m_HotspotY);
|
|
}
|
|
|
|
if (m_Zoomable) {
|
|
float zoom = ((CAdGame *)Game)->m_Scene->GetZoomAt(m_PosX, m_PosY);
|
|
ret = ret * zoom / 100;
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CAdObject::Talk(char *Text, char *Sound, uint32 Duration, char *Stances, TTextAlign Align) {
|
|
if (!m_Sentence) m_Sentence = new CAdSentence(Game);
|
|
if (!m_Sentence) return;
|
|
|
|
if (m_ForcedTalkAnimName && m_ForcedTalkAnimUsed) {
|
|
SAFE_DELETE_ARRAY(m_ForcedTalkAnimName);
|
|
m_ForcedTalkAnimUsed = false;
|
|
}
|
|
|
|
SAFE_DELETE(m_Sentence->m_Sound);
|
|
|
|
m_Sentence->SetText(Text);
|
|
Game->m_StringTable->Expand(&m_Sentence->m_Text);
|
|
m_Sentence->SetStances(Stances);
|
|
m_Sentence->m_Duration = Duration;
|
|
m_Sentence->m_Align = Align;
|
|
m_Sentence->m_StartTime = Game->m_Timer;
|
|
m_Sentence->m_CurrentStance = -1;
|
|
m_Sentence->m_Font = m_Font == NULL ? Game->m_SystemFont : m_Font;
|
|
m_Sentence->m_Freezable = m_Freezable;
|
|
|
|
// try to locate speech file automatically
|
|
bool DeleteSound = false;
|
|
if (!Sound) {
|
|
char *Key = Game->m_StringTable->GetKey(Text);
|
|
if (Key) {
|
|
Sound = ((CAdGame *)Game)->FindSpeechFile(Key);
|
|
delete [] Key;
|
|
|
|
if (Sound) DeleteSound = true;
|
|
}
|
|
}
|
|
|
|
// load sound and set duration appropriately
|
|
if (Sound) {
|
|
CBSound *snd = new CBSound(Game);
|
|
if (snd && SUCCEEDED(snd->SetSound(Sound, SOUND_SPEECH, true))) {
|
|
m_Sentence->SetSound(snd);
|
|
if (m_Sentence->m_Duration <= 0) {
|
|
uint32 Length = snd->GetLength();
|
|
if (Length != 0) m_Sentence->m_Duration = Length;
|
|
}
|
|
} else delete snd;
|
|
}
|
|
|
|
// set duration by text length
|
|
if (m_Sentence->m_Duration <= 0) {// TODO: Avoid longs.
|
|
m_Sentence->m_Duration = MAX((unsigned long)1000, Game->m_SubtitlesSpeed * strlen(m_Sentence->m_Text));
|
|
}
|
|
|
|
|
|
int x, y, width, height;
|
|
|
|
x = m_PosX;
|
|
y = m_PosY;
|
|
|
|
if (!m_SceneIndependent && m_SubtitlesModRelative) {
|
|
x -= ((CAdGame *)Game)->m_Scene->GetOffsetLeft();
|
|
y -= ((CAdGame *)Game)->m_Scene->GetOffsetTop();
|
|
}
|
|
|
|
|
|
if (m_SubtitlesWidth > 0) width = m_SubtitlesWidth;
|
|
else {
|
|
if ((x < Game->m_Renderer->m_Width / 4 || x > Game->m_Renderer->m_Width * 0.75) && !Game->m_TouchInterface) {
|
|
width = MAX(Game->m_Renderer->m_Width / 4, MIN(x * 2, (Game->m_Renderer->m_Width - x) * 2));
|
|
} else width = Game->m_Renderer->m_Width / 2;
|
|
}
|
|
|
|
height = m_Sentence->m_Font->GetTextHeight((byte *)m_Sentence->m_Text, width);
|
|
|
|
y = y - height - GetHeight() - 5;
|
|
if (m_SubtitlesModRelative) {
|
|
x += m_SubtitlesModX;
|
|
y += m_SubtitlesModY;
|
|
} else {
|
|
x = m_SubtitlesModX;
|
|
y = m_SubtitlesModY;
|
|
}
|
|
if (m_SubtitlesModXCenter)
|
|
x = x - width / 2;
|
|
|
|
|
|
x = MIN(MAX(0, x), Game->m_Renderer->m_Width - width);
|
|
y = MIN(MAX(0, y), Game->m_Renderer->m_Height - height);
|
|
|
|
m_Sentence->m_Width = width;
|
|
|
|
|
|
m_Sentence->m_Pos.x = x;
|
|
m_Sentence->m_Pos.y = y;
|
|
|
|
|
|
if (m_SubtitlesModRelative) {
|
|
m_Sentence->m_Pos.x += ((CAdGame *)Game)->m_Scene->GetOffsetLeft();
|
|
m_Sentence->m_Pos.y += ((CAdGame *)Game)->m_Scene->GetOffsetTop();
|
|
}
|
|
|
|
m_Sentence->m_FixedPos = !m_SubtitlesModRelative;
|
|
|
|
|
|
m_Sentence->SetupTalkFile(Sound);
|
|
|
|
m_State = STATE_TALKING;
|
|
|
|
if (DeleteSound) delete [] Sound;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::Reset() {
|
|
if (m_State == STATE_PLAYING_ANIM && m_AnimSprite != NULL) {
|
|
SAFE_DELETE(m_AnimSprite);
|
|
} else if (m_State == STATE_TALKING && m_Sentence) {
|
|
m_Sentence->Finish();
|
|
}
|
|
|
|
m_State = m_NextState = STATE_READY;
|
|
|
|
Game->m_ScEngine->ResetObject(this);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::Persist(CBPersistMgr *PersistMgr) {
|
|
CBObject::Persist(PersistMgr);
|
|
|
|
PersistMgr->Transfer(TMEMBER(m_Active));
|
|
PersistMgr->Transfer(TMEMBER(m_BlockRegion));
|
|
PersistMgr->Transfer(TMEMBER(m_CurrentBlockRegion));
|
|
PersistMgr->Transfer(TMEMBER(m_CurrentWptGroup));
|
|
PersistMgr->Transfer(TMEMBER(m_CurrentSprite));
|
|
PersistMgr->Transfer(TMEMBER(m_Drawn));
|
|
PersistMgr->Transfer(TMEMBER(m_Font));
|
|
PersistMgr->Transfer(TMEMBER(m_IgnoreItems));
|
|
PersistMgr->Transfer(TMEMBER_INT(m_NextState));
|
|
PersistMgr->Transfer(TMEMBER(m_Sentence));
|
|
PersistMgr->Transfer(TMEMBER_INT(m_State));
|
|
PersistMgr->Transfer(TMEMBER(m_AnimSprite));
|
|
PersistMgr->Transfer(TMEMBER(m_SceneIndependent));
|
|
PersistMgr->Transfer(TMEMBER(m_ForcedTalkAnimName));
|
|
PersistMgr->Transfer(TMEMBER(m_ForcedTalkAnimUsed));
|
|
PersistMgr->Transfer(TMEMBER(m_TempSprite2));
|
|
PersistMgr->Transfer(TMEMBER_INT(m_Type));
|
|
PersistMgr->Transfer(TMEMBER(m_WptGroup));
|
|
PersistMgr->Transfer(TMEMBER(m_StickRegion));
|
|
PersistMgr->Transfer(TMEMBER(m_SubtitlesModRelative));
|
|
PersistMgr->Transfer(TMEMBER(m_SubtitlesModX));
|
|
PersistMgr->Transfer(TMEMBER(m_SubtitlesModY));
|
|
PersistMgr->Transfer(TMEMBER(m_SubtitlesModXCenter));
|
|
PersistMgr->Transfer(TMEMBER(m_SubtitlesWidth));
|
|
PersistMgr->Transfer(TMEMBER(m_Inventory));
|
|
PersistMgr->Transfer(TMEMBER(m_PartEmitter));
|
|
|
|
for (int i = 0; i < MAX_NUM_REGIONS; i++) PersistMgr->Transfer(TMEMBER(m_CurrentRegions[i]));
|
|
|
|
m_AttachmentsPre.Persist(PersistMgr);
|
|
m_AttachmentsPost.Persist(PersistMgr);
|
|
PersistMgr->Transfer(TMEMBER(m_RegisterAlias));
|
|
|
|
PersistMgr->Transfer(TMEMBER(m_PartFollowParent));
|
|
PersistMgr->Transfer(TMEMBER(m_PartOffsetX));
|
|
PersistMgr->Transfer(TMEMBER(m_PartOffsetY));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::UpdateSounds() {
|
|
if (m_Sentence && m_Sentence->m_Sound)
|
|
UpdateOneSound(m_Sentence->m_Sound);
|
|
|
|
return CBObject::UpdateSounds();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::ResetSoundPan() {
|
|
if (m_Sentence && m_Sentence->m_Sound) {
|
|
m_Sentence->m_Sound->SetPan(0.0f);
|
|
}
|
|
return CBObject::ResetSoundPan();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CAdObject::GetExtendedFlag(char *FlagName) {
|
|
if (!FlagName) return false;
|
|
else if (strcmp(FlagName, "usable") == 0) return true;
|
|
|
|
else return CBObject::GetExtendedFlag(FlagName);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::SaveAsText(CBDynBuffer *Buffer, int Indent) {
|
|
if (m_BlockRegion) m_BlockRegion->SaveAsText(Buffer, Indent + 2, "BLOCKED_REGION");
|
|
if (m_WptGroup) m_WptGroup->SaveAsText(Buffer, Indent + 2);
|
|
|
|
CBBase::SaveAsText(Buffer, Indent + 2);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::UpdateBlockRegion() {
|
|
CAdGame *AdGame = (CAdGame *)Game;
|
|
if (AdGame->m_Scene) {
|
|
if (m_BlockRegion && m_CurrentBlockRegion)
|
|
m_CurrentBlockRegion->Mimic(m_BlockRegion, m_Zoomable ? AdGame->m_Scene->GetScaleAt(m_PosY) : 100.0f, m_PosX, m_PosY);
|
|
|
|
if (m_WptGroup && m_CurrentWptGroup)
|
|
m_CurrentWptGroup->Mimic(m_WptGroup, m_Zoomable ? AdGame->m_Scene->GetScaleAt(m_PosY) : 100.0f, m_PosX, m_PosY);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CAdInventory *CAdObject::GetInventory() {
|
|
if (!m_Inventory) {
|
|
m_Inventory = new CAdInventory(Game);
|
|
((CAdGame *)Game)->RegisterInventory(m_Inventory);
|
|
}
|
|
return m_Inventory;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::AfterMove() {
|
|
CAdRegion *NewRegions[MAX_NUM_REGIONS];
|
|
|
|
((CAdGame *)Game)->m_Scene->GetRegionsAt(m_PosX, m_PosY, NewRegions, MAX_NUM_REGIONS);
|
|
for (int i = 0; i < MAX_NUM_REGIONS; i++) {
|
|
if (!NewRegions[i]) break;
|
|
bool RegFound = false;
|
|
for (int j = 0; j < MAX_NUM_REGIONS; j++) {
|
|
if (m_CurrentRegions[j] == NewRegions[i]) {
|
|
m_CurrentRegions[j] = NULL;
|
|
RegFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!RegFound) NewRegions[i]->ApplyEvent("ActorEntry");
|
|
}
|
|
|
|
for (int i = 0; i < MAX_NUM_REGIONS; i++) {
|
|
if (m_CurrentRegions[i] && Game->ValidObject(m_CurrentRegions[i])) {
|
|
m_CurrentRegions[i]->ApplyEvent("ActorLeave");
|
|
}
|
|
m_CurrentRegions[i] = NewRegions[i];
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::InvalidateCurrRegions() {
|
|
for (int i = 0; i < MAX_NUM_REGIONS; i++) m_CurrentRegions[i] = NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::GetScale(float *ScaleX, float *ScaleY) {
|
|
if (m_Zoomable) {
|
|
if (m_ScaleX >= 0 || m_ScaleY >= 0) {
|
|
*ScaleX = m_ScaleX < 0 ? 100 : m_ScaleX;
|
|
*ScaleY = m_ScaleY < 0 ? 100 : m_ScaleY;
|
|
} else if (m_Scale >= 0) *ScaleX = *ScaleY = m_Scale;
|
|
else *ScaleX = *ScaleY = ((CAdGame *)Game)->m_Scene->GetZoomAt(m_PosX, m_PosY) + m_RelativeScale;
|
|
} else {
|
|
*ScaleX = *ScaleY = 100;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::UpdateSpriteAttachments() {
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
m_AttachmentsPre[i]->Update();
|
|
}
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
m_AttachmentsPost[i]->Update();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::DisplaySpriteAttachments(bool PreDisplay) {
|
|
if (PreDisplay) {
|
|
for (int i = 0; i < m_AttachmentsPre.GetSize(); i++) {
|
|
DisplaySpriteAttachment(m_AttachmentsPre[i]);
|
|
}
|
|
} else {
|
|
for (int i = 0; i < m_AttachmentsPost.GetSize(); i++) {
|
|
DisplaySpriteAttachment(m_AttachmentsPost[i]);
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::DisplaySpriteAttachment(CAdObject *Attachment) {
|
|
if (!Attachment->m_Active) return S_OK;
|
|
|
|
float ScaleX, ScaleY;
|
|
GetScale(&ScaleX, &ScaleY);
|
|
|
|
int OrigX = Attachment->m_PosX;
|
|
int OrigY = Attachment->m_PosY;
|
|
|
|
// inherit position from owner
|
|
Attachment->m_PosX = this->m_PosX + Attachment->m_PosX * ScaleX / 100.0f;
|
|
Attachment->m_PosY = this->m_PosY + Attachment->m_PosY * ScaleY / 100.0f;
|
|
|
|
// inherit other props
|
|
Attachment->m_AlphaColor = this->m_AlphaColor;
|
|
Attachment->m_BlendMode = this->m_BlendMode;
|
|
|
|
Attachment->m_Scale = this->m_Scale;
|
|
Attachment->m_RelativeScale = this->m_RelativeScale;
|
|
Attachment->m_ScaleX = this->m_ScaleX;
|
|
Attachment->m_ScaleY = this->m_ScaleY;
|
|
|
|
Attachment->m_Rotate = this->m_Rotate;
|
|
Attachment->m_RelativeRotate = this->m_RelativeRotate;
|
|
Attachment->m_RotateValid = this->m_RotateValid;
|
|
|
|
Attachment->m_RegisterAlias = this;
|
|
Attachment->m_Registrable = this->m_Registrable;
|
|
|
|
HRESULT ret = Attachment->Display();
|
|
|
|
Attachment->m_PosX = OrigX;
|
|
Attachment->m_PosY = OrigY;
|
|
|
|
return ret;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CPartEmitter *CAdObject::CreateParticleEmitter(bool FollowParent, int OffsetX, int OffsetY) {
|
|
m_PartFollowParent = FollowParent;
|
|
m_PartOffsetX = OffsetX;
|
|
m_PartOffsetY = OffsetY;
|
|
|
|
if (!m_PartEmitter) {
|
|
m_PartEmitter = new CPartEmitter(Game, this);
|
|
if (m_PartEmitter) {
|
|
Game->RegisterObject(m_PartEmitter);
|
|
}
|
|
}
|
|
UpdatePartEmitter();
|
|
return m_PartEmitter;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAdObject::UpdatePartEmitter() {
|
|
if (!m_PartEmitter) return E_FAIL;
|
|
|
|
if (m_PartFollowParent) {
|
|
float ScaleX, ScaleY;
|
|
GetScale(&ScaleX, &ScaleY);
|
|
|
|
m_PartEmitter->m_PosX = m_PosX + (ScaleX / 100.0f) * m_PartOffsetX;
|
|
m_PartEmitter->m_PosY = m_PosY + (ScaleY / 100.0f) * m_PartOffsetY;
|
|
}
|
|
return m_PartEmitter->Update();
|
|
}
|
|
|
|
} // end of namespace WinterMute
|