//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
HRESULT CBKeyboardState::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// IsKeyDown
	//////////////////////////////////////////////////////////////////////////
	if (strcmp(Name, "IsKeyDown")==0)
	{
		Stack->CorrectParams(1);
		CScValue* val = Stack->Pop();
		int vKey;

		if (val->m_Type==VAL_STRING && strlen(val->GetString())>0)
		{
			char* str = val->GetString();
			if(str[0]>='A' && str[0]<='Z') str[0] += ('a' - 'A');
			vKey = (int)str[0];
		}
		else vKey = val->GetInt();

    	const Uint8* state = SDL_GetKeyboardState(NULL);
		SDL_Scancode scanCode = SDL_GetScancodeFromKey(VKeyToKeyCode(vKey));
		bool isDown = state[scanCode] > 0;

		Stack->PushBool(isDown);
		return S_OK;
	}

	else return CBScriptable::ScCallMethod(Script, Stack, ThisStack, Name);
}
Example #2
0
CSXDate::CSXDate(CBGame *inGame, CScStack *Stack): CBScriptable(inGame) {
	Stack->CorrectParams(6);

	memset(&m_tm, 0, sizeof(m_tm));

	CScValue *valYear = Stack->Pop();
	m_tm.tm_year = valYear->GetInt() - 1900;
	m_tm.tm_mon = Stack->Pop()->GetInt() - 1;
	m_tm.tm_mday = Stack->Pop()->GetInt();
	m_tm.tm_hour = Stack->Pop()->GetInt();
	m_tm.tm_min = Stack->Pop()->GetInt();
	m_tm.tm_sec = Stack->Pop()->GetInt();

	if (valYear->IsNULL()) {
		time_t TimeNow;
		time(&TimeNow);
		memcpy(&m_tm, localtime(&TimeNow), sizeof(m_tm));
	}

	mktime(&m_tm);
}
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
HRESULT CBSprite::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// GetFrame
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "GetFrame")==0)
	{
		Stack->CorrectParams(1);
		int Index = Stack->Pop()->GetInt(-1);
		if(Index<0 || Index>=m_Frames.GetSize())
		{
			Script->RuntimeError("Sprite.GetFrame: Frame index %d is out of range.", Index);
			Stack->PushNULL();
		}
		else Stack->PushNative(m_Frames[Index], true);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// DeleteFrame
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "DeleteFrame")==0)
	{
		Stack->CorrectParams(1);
		CScValue* Val = Stack->Pop();
		if(Val->IsInt())
		{
			int Index = Val->GetInt(-1);
			if(Index<0 || Index>=m_Frames.GetSize())
			{
				Script->RuntimeError("Sprite.DeleteFrame: Frame index %d is out of range.", Index);
			}			
		}
		else
		{
			CBFrame* Frame = (CBFrame*)Val->GetNative();
			for(int i=0; i<m_Frames.GetSize(); i++)
			{
				if(m_Frames[i]==Frame)
				{
					if(i==m_CurrentFrame) m_LastFrameTime = 0;
					delete m_Frames[i];
					m_Frames.RemoveAt(i);
					break;
				}
			}
		}
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Reset
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "Reset")==0)
	{
		Stack->CorrectParams(0);
		Reset();
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// AddFrame
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "AddFrame")==0)
	{
		Stack->CorrectParams(1);
		CScValue* Val = Stack->Pop();
		char* Filename = NULL;
		if(!Val->IsNULL()) Filename = Val->GetString();

		CBFrame* Frame = new CBFrame(Game);		
		if(Filename!=NULL)
		{
			CBSubFrame* Sub = new CBSubFrame(Game);			
			if(SUCCEEDED(Sub->SetSurface(Filename)))
			{
				Sub->SetDefaultRect();
				Frame->m_Subframes.Add(Sub);
			}
			else delete Sub;
		}
		m_Frames.Add(Frame);

		Stack->PushNative(Frame, true);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// InsertFrame
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "InsertFrame")==0)
	{
		Stack->CorrectParams(2);
		int Index = Stack->Pop()->GetInt();
		if(Index<0) Index = 0;

		CScValue* Val = Stack->Pop();
		char* Filename = NULL;
		if(!Val->IsNULL()) Filename = Val->GetString();

		CBFrame* Frame = new CBFrame(Game);		
		if(Filename!=NULL)
		{
			CBSubFrame* Sub = new CBSubFrame(Game);			
			if(SUCCEEDED(Sub->SetSurface(Filename))) Frame->m_Subframes.Add(Sub);
			else delete Sub;
		}

		if(Index>=m_Frames.GetSize()) m_Frames.Add(Frame);
		else m_Frames.InsertAt(Index, Frame);

		Stack->PushNative(Frame, true);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Pause
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "Pause")==0)
	{
		Stack->CorrectParams(0);
		m_Paused = true;
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// Play
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "Play")==0)
	{
		Stack->CorrectParams(0);
		m_Paused = false;
		Stack->PushNULL();
		return S_OK;
	}

	else return CBScriptHolder::ScCallMethod(Script, Stack, ThisStack, Name);
}
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
HRESULT CUIWindow::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
    //////////////////////////////////////////////////////////////////////////
    // GetWidget / GetControl
    //////////////////////////////////////////////////////////////////////////
    if(strcmp(Name, "GetWidget")==0 || strcmp(Name, "GetControl")==0)
    {
        Stack->CorrectParams(1);
        CScValue* val = Stack->Pop();
        if(val->GetType()==VAL_INT)
        {
            int widget= val->GetInt();
            if(widget<0 || widget>=m_Widgets.GetSize()) Stack->PushNULL();
            else Stack->PushNative(m_Widgets[widget], true);
        }
        else
        {
            for(int i=0; i<m_Widgets.GetSize(); i++)
            {
                if(CBPlatform::stricmp(m_Widgets[i]->m_Name, val->GetString())==0)
                {
                    Stack->PushNative(m_Widgets[i], true);
                    return S_OK;
                }
            }
            Stack->PushNULL();
        }

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // SetInactiveFont
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "SetInactiveFont")==0)
    {
        Stack->CorrectParams(1);

        if(m_FontInactive) Game->m_FontStorage->RemoveFont(m_FontInactive);
        m_FontInactive = Game->m_FontStorage->AddFont(Stack->Pop()->GetString());
        Stack->PushBool(m_FontInactive!=NULL);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // SetInactiveImage
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "SetInactiveImage")==0)
    {
        Stack->CorrectParams(1);

        SAFE_DELETE(m_ImageInactive);
        m_ImageInactive = new CBSprite(Game);
        char* Filename = Stack->Pop()->GetString();
        if(!m_ImageInactive || FAILED(m_ImageInactive->LoadFile(Filename)))
        {
            SAFE_DELETE(m_ImageInactive);
            Stack->PushBool(false);
        }
        else Stack->PushBool(true);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // GetInactiveImage
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "GetInactiveImage")==0)
    {
        Stack->CorrectParams(0);
        if(!m_ImageInactive || !m_ImageInactive->m_Filename) Stack->PushNULL();
        else Stack->PushString(m_ImageInactive->m_Filename);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // GetInactiveImageObject
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "GetInactiveImageObject")==0)
    {
        Stack->CorrectParams(0);
        if(!m_ImageInactive) Stack->PushNULL();
        else Stack->PushNative(m_ImageInactive, true);

        return S_OK;
    }


    //////////////////////////////////////////////////////////////////////////
    // Close
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "Close")==0)
    {
        Stack->CorrectParams(0);
        Stack->PushBool(SUCCEEDED(Close()));
        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // GoExclusive
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "GoExclusive")==0)
    {
        Stack->CorrectParams(0);
        GoExclusive();
        Script->WaitFor(this);
        Stack->PushNULL();
        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // GoSystemExclusive
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "GoSystemExclusive")==0)
    {
        Stack->CorrectParams(1);
        char* Event = Stack->Pop()->GetString();
        GoSystemExclusive();

        if (Event != NULL)
        {
            ApplyEvent(Event);
        }
        Script->WaitFor(this);
        Stack->PushNULL();
        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // Center
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "Center")==0)
    {
        Stack->CorrectParams(0);
        m_PosX = (Game->m_Renderer->m_Width - m_Width) / 2;
        m_PosY = (Game->m_Renderer->m_Height - m_Height) / 2;
        Stack->PushNULL();
        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // LoadFromFile
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "LoadFromFile")==0)
    {
        Stack->CorrectParams(1);

        CScValue* Val = Stack->Pop();
        Cleanup();
        if(!Val->IsNULL())
        {
            Stack->PushBool(SUCCEEDED(LoadFile(Val->GetString())));
        }
        else Stack->PushBool(true);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // CreateButton
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "CreateButton")==0)
    {
        Stack->CorrectParams(1);
        CScValue* Val = Stack->Pop();

        CUIButton* Btn = new CUIButton(Game);
        if(!Val->IsNULL()) Btn->SetName(Val->GetString());
        Stack->PushNative(Btn, true);

        Btn->m_Parent = this;
        m_Widgets.Add(Btn);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // CreateStatic
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "CreateStatic")==0)
    {
        Stack->CorrectParams(1);
        CScValue* Val = Stack->Pop();

        CUIText* Sta = new CUIText(Game);
        if(!Val->IsNULL()) Sta->SetName(Val->GetString());
        Stack->PushNative(Sta, true);

        Sta->m_Parent = this;
        m_Widgets.Add(Sta);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // CreateEditor
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "CreateEditor")==0)
    {
        Stack->CorrectParams(1);
        CScValue* Val = Stack->Pop();

        CUIEdit* Edi = new CUIEdit(Game);
        if(!Val->IsNULL()) Edi->SetName(Val->GetString());
        Stack->PushNative(Edi, true);

        Edi->m_Parent = this;
        m_Widgets.Add(Edi);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // CreateWindow
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "CreateWindow")==0)
    {
        Stack->CorrectParams(1);
        CScValue* Val = Stack->Pop();

        CUIWindow* Win = new CUIWindow(Game);
        if(!Val->IsNULL()) Win->SetName(Val->GetString());
        Stack->PushNative(Win, true);

        Win->m_Parent = this;
        m_Widgets.Add(Win);

        return S_OK;
    }

    //////////////////////////////////////////////////////////////////////////
    // DeleteControl / DeleteButton / DeleteStatic / DeleteEditor / DeleteWindow
    //////////////////////////////////////////////////////////////////////////
    else if(strcmp(Name, "DeleteControl")==0 || strcmp(Name, "DeleteButton")==0 || strcmp(Name, "DeleteStatic")==0 || strcmp(Name, "DeleteEditor")==0 || strcmp(Name, "DeleteWindow")==0)
    {
        Stack->CorrectParams(1);
        CScValue* val = Stack->Pop();
        CUIObject* obj = (CUIObject*)val->GetNative();

        for(int i=0; i<m_Widgets.GetSize(); i++)
        {
            if(m_Widgets[i]==obj)
            {
                delete m_Widgets[i];
                m_Widgets.RemoveAt(i);
                if(val->GetType()==VAL_VARIABLE_REF) val->SetNULL();
            }
        }
        Stack->PushNULL();
        return S_OK;
    }
    else if SUCCEEDED(Game->WindowScriptMethodHook(this, Script, Stack, Name)) return S_OK;

    else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
HRESULT CAdLayer::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// GetNode
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "GetNode")==0)
	{
		Stack->CorrectParams(1);
		CScValue* val = Stack->Pop();
		int node = -1;
		
		if(val->m_Type==VAL_INT) node = val->GetInt();
		else{ // get by name
			for(int i=0; i<m_Nodes.GetSize(); i++){
				if( (m_Nodes[i]->m_Type==OBJECT_ENTITY && CBPlatform::stricmp(m_Nodes[i]->m_Entity->m_Name, val->GetString())==0) ||
					(m_Nodes[i]->m_Type==OBJECT_REGION && CBPlatform::stricmp(m_Nodes[i]->m_Region->m_Name, val->GetString())==0)){
					node = i;
					break;
				}					
			}
		}

		if(node<0 || node>= m_Nodes.GetSize()) Stack->PushNULL();
		else{
			switch(m_Nodes[node]->m_Type){
				case OBJECT_ENTITY:
					Stack->PushNative(m_Nodes[node]->m_Entity, true);
					break;
				case OBJECT_REGION:
					Stack->PushNative(m_Nodes[node]->m_Region, true);
					break;
				default:
					Stack->PushNULL();
			}
		}
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// AddRegion / AddEntity
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "AddRegion")==0 || strcmp(Name, "AddEntity")==0)
	{
		Stack->CorrectParams(1);
		CScValue* Val = Stack->Pop();

		CAdSceneNode* Node = new CAdSceneNode(Game);
		if(strcmp(Name, "AddRegion")==0)
		{
			CAdRegion* Region = new CAdRegion(Game);
			if(!Val->IsNULL()) Region->SetName(Val->GetString());
			Node->SetRegion(Region);
			Stack->PushNative(Region, true);
		}
		else
		{
			CAdEntity* Entity = new CAdEntity(Game);
			if(!Val->IsNULL()) Entity->SetName(Val->GetString());
			Node->SetEntity(Entity);
			Stack->PushNative(Entity, true);
		}
		m_Nodes.Add(Node);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// InsertRegion / InsertEntity
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "InsertRegion")==0 || strcmp(Name, "InsertEntity")==0)
	{
		Stack->CorrectParams(2);
		int Index = Stack->Pop()->GetInt();
		CScValue* Val = Stack->Pop();

		CAdSceneNode* Node = new CAdSceneNode(Game);
		if(strcmp(Name, "InsertRegion")==0)
		{
			CAdRegion* Region = new CAdRegion(Game);
			if(!Val->IsNULL()) Region->SetName(Val->GetString());
			Node->SetRegion(Region);
			Stack->PushNative(Region, true);
		}
		else
		{
			CAdEntity* Entity = new CAdEntity(Game);
			if(!Val->IsNULL()) Entity->SetName(Val->GetString());
			Node->SetEntity(Entity);
			Stack->PushNative(Entity, true);
		}
		if(Index < 0) Index = 0;
		if(Index <= m_Nodes.GetSize() - 1) m_Nodes.InsertAt(Index, Node);
		else m_Nodes.Add(Node);

		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// DeleteNode
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "DeleteNode")==0)
	{
		Stack->CorrectParams(1);
		CScValue* Val = Stack->Pop();

		CAdSceneNode* ToDelete = NULL;
		if(Val->IsNative())
		{
			CBScriptable* Temp = Val->GetNative();
			for(int i=0; i<m_Nodes.GetSize(); i++)
			{
				if(m_Nodes[i]->m_Region==Temp || m_Nodes[i]->m_Entity==Temp)
				{
					ToDelete = m_Nodes[i];
					break;
				}
			}
		}
		else
		{
			int Index = Val->GetInt();
			if(Index >= 0 && Index < m_Nodes.GetSize())
			{
				ToDelete = m_Nodes[Index];
			}
		}
		if(ToDelete==NULL)
		{
			Stack->PushBool(false);
			return S_OK;
		}

		for(int i=0; i<m_Nodes.GetSize(); i++)
		{
			if(m_Nodes[i]==ToDelete)
			{				
				SAFE_DELETE(m_Nodes[i]);
				m_Nodes.RemoveAt(i);
				break;
			}
		}
		Stack->PushBool(true);
		return S_OK;
	}

	else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name);
}
//////////////////////////////////////////////////////////////////////////
// high level scripting interface
//////////////////////////////////////////////////////////////////////////
HRESULT CAdActor::ScCallMethod(CScScript* Script, CScStack *Stack, CScStack *ThisStack, char *Name)
{
	//////////////////////////////////////////////////////////////////////////
	// GoTo / GoToAsync
	//////////////////////////////////////////////////////////////////////////
	if(strcmp(Name, "GoTo")==0 || strcmp(Name, "GoToAsync")==0)
	{
		Stack->CorrectParams(2);
		int X = Stack->Pop()->GetInt();
		int Y = Stack->Pop()->GetInt();
		GoTo(X, Y);
		if(strcmp(Name, "GoToAsync")!=0) Script->WaitForExclusive(this);
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// GoToObject / GoToObjectAsync
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "GoToObject")==0 || strcmp(Name, "GoToObjectAsync")==0)
	{
		Stack->CorrectParams(1);
		CScValue* Val = Stack->Pop();
		if(!Val->IsNative())
		{
			Script->RuntimeError("actor.%s method accepts an entity refrence only", Name);
			Stack->PushNULL();
			return S_OK;
		}
		CAdObject* Obj = (CAdObject*)Val->GetNative();
		if(!Obj || Obj->m_Type != OBJECT_ENTITY)
		{
			Script->RuntimeError("actor.%s method accepts an entity refrence only", Name);
			Stack->PushNULL();
			return S_OK;
		}
		CAdEntity* Ent = (CAdEntity*)Obj;
		if(Ent->m_WalkToX==0 && Ent->m_WalkToY==0) GoTo(Ent->m_PosX, Ent->m_PosY);
		else GoTo(Ent->m_WalkToX, Ent->m_WalkToY, Ent->m_WalkToDir);
		if(strcmp(Name, "GoToObjectAsync")!=0) Script->WaitForExclusive(this);
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// TurnTo / TurnToAsync
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "TurnTo")==0 || strcmp(Name, "TurnToAsync")==0)
	{
		Stack->CorrectParams(1);
		int dir;
		CScValue* val = Stack->Pop();
		
		// turn to object?
		if(val->IsNative() && Game->ValidObject((CBObject*)val->GetNative()))
		{
			CBObject* obj = (CBObject*)val->GetNative();
			int angle = (int)(atan2((double)(obj->m_PosY - m_PosY), (double)(obj->m_PosX - m_PosX)) * (180/3.14));
			dir = (int)AngleToDirection(angle);
		}
		// otherwise turn to direction
		else dir = val->GetInt();

		if(dir >= 0 && dir < NUM_DIRECTIONS)
		{
			TurnTo((TDirection)dir);
			if(strcmp(Name, "TurnToAsync")!=0) Script->WaitForExclusive(this);
		}
		Stack->PushNULL();
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// IsWalking
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "IsWalking")==0)
	{
		Stack->CorrectParams(0);
		Stack->PushBool(m_State==STATE_FOLLOWING_PATH);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// MergeAnims
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "MergeAnims")==0)
	{
		Stack->CorrectParams(1);
		Stack->PushBool(SUCCEEDED(MergeAnims(Stack->Pop()->GetString())));
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// UnloadAnim
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "UnloadAnim")==0)
	{
		Stack->CorrectParams(1);
		char* AnimName = Stack->Pop()->GetString();

		bool Found = false;
		for(int i=0; i<m_Anims.GetSize(); i++)
		{
			if(stricmp(m_Anims[i]->m_Name, AnimName)==0)
			{
				// invalidate sprites in use
				if(m_Anims[i]->ContainsSprite(m_TempSprite2)) m_TempSprite2 = NULL;
				if(m_Anims[i]->ContainsSprite(m_CurrentSprite)) m_CurrentSprite = NULL;
				if(m_Anims[i]->ContainsSprite(m_AnimSprite2)) m_AnimSprite2 = NULL;

				SAFE_DELETE(m_Anims[i]);
				m_Anims.RemoveAt(i);
				i--;
				Found = true;
			}
		}
		Stack->PushBool(Found);
		return S_OK;
	}

	//////////////////////////////////////////////////////////////////////////
	// HasAnim
	//////////////////////////////////////////////////////////////////////////
	else if(strcmp(Name, "HasAnim")==0)
	{
		Stack->CorrectParams(1);
		char* AnimName = Stack->Pop()->GetString();
		Stack->PushBool(GetAnimByName(AnimName) != NULL);
		return S_OK;
	}

	else return CAdTalkHolder::ScCallMethod(Script, Stack, ThisStack, Name);
}