forked from Mirrors/openclonk
269 lines
7.9 KiB
C++
269 lines
7.9 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 1998-2000 Matthes Bender
|
|
* Copyright (c) 2001-2002, 2005, 2007 Sven Eberhardt
|
|
* Copyright (c) 2003-2005 Peter Wortmann
|
|
* Copyright (c) 2006 Armin Burgmeier
|
|
* Copyright (c) 2006-2007 Günther Brammer
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
*
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
* to OpenClonk.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
* See isc_license.txt for full license and disclaimer.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
* See clonk_trademark_license.txt for full license.
|
|
*/
|
|
|
|
/* Handles script file components (calls, inheritance, function maps) */
|
|
|
|
#include <C4Include.h>
|
|
#include <C4ScriptHost.h>
|
|
|
|
#ifndef BIG_C4INCLUDE
|
|
#include <C4Console.h>
|
|
#include <C4ObjectCom.h>
|
|
#include <C4Object.h>
|
|
#include <C4Game.h>
|
|
#include <C4GameObjects.h>
|
|
#endif
|
|
|
|
/*--- C4ScriptHost ---*/
|
|
|
|
C4ScriptHost::C4ScriptHost() { Default(); }
|
|
C4ScriptHost::~C4ScriptHost() { Clear(); }
|
|
|
|
void C4ScriptHost::Default()
|
|
{
|
|
C4AulScript::Default();
|
|
C4ComponentHost::Default();
|
|
pStringTable = NULL;
|
|
}
|
|
|
|
void C4ScriptHost::Clear()
|
|
{
|
|
C4AulScript::Clear();
|
|
C4ComponentHost::Clear();
|
|
pStringTable = NULL;
|
|
}
|
|
|
|
BOOL C4ScriptHost::Load(const char *szName, C4Group &hGroup, const char *szFilename,
|
|
const char *szLanguage, C4Def *pDef, class C4LangStringTable *pLocalTable, bool fLoadTable)
|
|
{
|
|
// Set definition and id
|
|
Def = pDef;
|
|
// Base load
|
|
BOOL fSuccess = C4ComponentHost::LoadAppend(szName,hGroup,szFilename,szLanguage);
|
|
// String Table
|
|
pStringTable = pLocalTable;
|
|
// load it if specified
|
|
if (pStringTable && fLoadTable)
|
|
pStringTable->LoadEx("StringTbl", hGroup, C4CFN_ScriptStringTbl, szLanguage);
|
|
// set name
|
|
ScriptName.Format("%s" DirSep "%s", hGroup.GetFullName().getData(), Filename);
|
|
// preparse script
|
|
MakeScript();
|
|
// Success
|
|
return fSuccess;
|
|
}
|
|
|
|
|
|
void C4ScriptHost::MakeScript()
|
|
{
|
|
// clear prev
|
|
Script.Clear();
|
|
|
|
// create script
|
|
if (pStringTable)
|
|
{
|
|
pStringTable->ReplaceStrings(Data, Script, FilePath);
|
|
}
|
|
else
|
|
{
|
|
Script.Ref(Data);
|
|
}
|
|
|
|
// preparse script
|
|
Preparse();
|
|
}
|
|
|
|
void C4ScriptHost::Close()
|
|
{
|
|
// Base close
|
|
C4ComponentHost::Close();
|
|
// Make executable script
|
|
MakeScript();
|
|
// Update console
|
|
Console.UpdateInputCtrl();
|
|
}
|
|
|
|
int32_t C4ScriptHost::GetControlMethod(int32_t com, int32_t first, int32_t second)
|
|
{
|
|
return ((first >> com) & 0x01) | (((second >> com) & 0x01) << 1);
|
|
}
|
|
|
|
void C4ScriptHost::GetControlMethodMask(const char *szFunctionFormat, int32_t& first, int32_t& second)
|
|
{
|
|
first = second = 0;
|
|
//int32_t iResult = 0;
|
|
|
|
if (!Script) return;
|
|
|
|
// Scan for com defined control functions
|
|
int32_t iCom;
|
|
char szFunction[256+1];
|
|
for (iCom=0; iCom<ComOrderNum; iCom++)
|
|
{
|
|
sprintf( szFunction, szFunctionFormat, ComName( ComOrder(iCom) ) );
|
|
C4AulScriptFunc* func = GetSFunc(szFunction);
|
|
|
|
if(func)
|
|
{
|
|
first |= ((func->ControlMethod ) & 0x01) << iCom;
|
|
second |= ((func->ControlMethod >> 1) & 0x01) << iCom;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
C4Value C4ScriptHost::Call(const char *szFunction, C4Object *pObj, C4AulParSet *Pars, bool fPrivateCall, bool fPassError)
|
|
{
|
|
// get function
|
|
C4AulScriptFunc *pFn;
|
|
if (!(pFn = GetSFunc(szFunction, AA_PRIVATE))) return C4VNull;
|
|
// Call code
|
|
return pFn->Exec(pObj,Pars, fPassError);
|
|
}
|
|
|
|
BOOL C4ScriptHost::ReloadScript(const char *szPath)
|
|
{
|
|
// this?
|
|
if(SEqualNoCase(szPath, FilePath) || (pStringTable && SEqualNoCase(szPath, pStringTable->GetFilePath())))
|
|
{
|
|
// try reload
|
|
char szParentPath[_MAX_PATH + 1]; C4Group ParentGrp;
|
|
if(GetParentPath(szPath, szParentPath))
|
|
if(ParentGrp.Open(szParentPath))
|
|
if(Load(Name, ParentGrp, Filename, Config.General.Language, NULL, pStringTable))
|
|
return TRUE;
|
|
}
|
|
// call for childs
|
|
return C4AulScript::ReloadScript(szPath);
|
|
}
|
|
|
|
void C4ScriptHost::SetError(const char *szMessage)
|
|
{
|
|
|
|
}
|
|
|
|
const char *C4ScriptHost::GetControlDesc(const char *szFunctionFormat, int32_t iCom, C4ID *pidImage, int32_t* piImagePhase)
|
|
{
|
|
// Compose script function
|
|
char szFunction[256+1];
|
|
sprintf(szFunction,szFunctionFormat,ComName(iCom));
|
|
// Remove failsafe indicator
|
|
if (szFunction[0]=='~') memmove(szFunction,szFunction+1,sizeof(szFunction));
|
|
// Find function reference
|
|
C4AulScriptFunc *pFn = GetSFunc(szFunction);
|
|
// Get image id
|
|
if (pidImage) { if (Def) *pidImage=Def->id; else *pidImage=0; if (pFn) *pidImage=pFn->idImage; }
|
|
// Get image phase
|
|
if(piImagePhase) { *piImagePhase = 0; if(pFn) *piImagePhase = pFn->iImagePhase; }
|
|
// Return function desc
|
|
if (pFn && pFn->Desc.getLength()) return pFn->DescText.getData();
|
|
// No function
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*--- C4DefScriptHost ---*/
|
|
|
|
void C4DefScriptHost::Default()
|
|
{
|
|
C4ScriptHost::Default();
|
|
SFn_CalcValue = SFn_SellTo = SFn_ControlTransfer = SFn_CustomComponents = NULL;
|
|
ControlMethod[0]=ControlMethod[1]=ContainedControlMethod[0]=ContainedControlMethod[1]=ActivationControlMethod[0]=ActivationControlMethod[1]=0;
|
|
}
|
|
|
|
void C4DefScriptHost::AfterLink()
|
|
{
|
|
C4AulScript::AfterLink();
|
|
// Search cached functions
|
|
char WhereStr[C4MaxName+18];
|
|
SFn_CalcValue = GetSFunc(PSF_CalcValue , AA_PROTECTED);
|
|
SFn_SellTo = GetSFunc(PSF_SellTo , AA_PROTECTED);
|
|
SFn_ControlTransfer = GetSFunc(PSF_ControlTransfer, AA_PROTECTED);
|
|
SFn_CustomComponents = GetSFunc(PSF_GetCustomComponents, AA_PROTECTED);
|
|
if (Def)
|
|
{
|
|
C4AulAccess CallAccess = /*Strict ? AA_PROTECTED : */AA_PRIVATE;
|
|
for (int32_t cnt=0; cnt<Def->ActNum; cnt++)
|
|
{
|
|
C4ActionDef *pad=&Def->ActMap[cnt];
|
|
sprintf(WhereStr, "Action %s: StartCall", pad->Name); pad->StartCall = GetSFuncWarn((const char *) &pad->SStartCall, CallAccess, WhereStr);
|
|
sprintf(WhereStr, "Action %s: PhaseCall", pad->Name); pad->PhaseCall = GetSFuncWarn((const char *) &pad->SPhaseCall, CallAccess, WhereStr);
|
|
sprintf(WhereStr, "Action %s: EndCall" , pad->Name); pad->EndCall = GetSFuncWarn((const char *) &pad->SEndCall, CallAccess, WhereStr);
|
|
sprintf(WhereStr, "Action %s: AbortCall", pad->Name); pad->AbortCall = GetSFuncWarn((const char *) &pad->SAbortCall, CallAccess, WhereStr);
|
|
}
|
|
Def->TimerCall=GetSFuncWarn((const char *) Def->STimerCall, CallAccess, "TimerCall");
|
|
}
|
|
// Check if there are any Control/Contained/Activation script functions
|
|
GetControlMethodMask(PSF_Control, ControlMethod[0], ControlMethod[1]);
|
|
GetControlMethodMask(PSF_ContainedControl, ContainedControlMethod[0], ContainedControlMethod[1]);
|
|
GetControlMethodMask(PSF_Activate, ActivationControlMethod[0], ActivationControlMethod[1]);
|
|
}
|
|
|
|
|
|
|
|
/*--- C4GameScriptHost ---*/
|
|
|
|
C4GameScriptHost::C4GameScriptHost(): Counter(0), Go(false) { }
|
|
C4GameScriptHost::~C4GameScriptHost() { }
|
|
|
|
|
|
void C4GameScriptHost::Default()
|
|
{
|
|
C4ScriptHost::Default();
|
|
Counter=0;
|
|
Go=FALSE;
|
|
}
|
|
|
|
BOOL C4GameScriptHost::Execute()
|
|
{
|
|
if (!Script) return FALSE;
|
|
char buffer[500];
|
|
if (Go && !::Game.iTick10)
|
|
{
|
|
sprintf(buffer,PSF_Script,Counter++);
|
|
return !! Call(buffer);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
C4Value C4GameScriptHost::GRBroadcast(const char *szFunction, C4AulParSet *pPars, bool fPassError, bool fRejectTest)
|
|
{
|
|
// call objects first - scenario script might overwrite hostility, etc...
|
|
C4Object *pObj;
|
|
for (C4ObjectLink *clnk=::Objects.ObjectsInt().First; clnk; clnk=clnk->Next) if (pObj=clnk->Obj)
|
|
if (pObj->Category & (C4D_Goal | C4D_Rule | C4D_Environment))
|
|
if (pObj->Status)
|
|
{
|
|
C4Value vResult(pObj->Call(szFunction, pPars, fPassError));
|
|
// rejection tests abort on first nonzero result
|
|
if (fRejectTest) if (!!vResult) return vResult;
|
|
}
|
|
// scenario script call
|
|
return Call(szFunction, 0, pPars, fPassError);
|
|
}
|
|
|
|
void C4GameScriptHost::CompileFunc(StdCompiler *pComp)
|
|
{
|
|
pComp->Value(mkNamingAdapt(Go, "Go", false));
|
|
pComp->Value(mkNamingAdapt(Counter, "Counter", 0));
|
|
}
|