예제 #1
0
void CListWrapper::PaintImageAtCursor (CG16bitImage &Dest, int x, int y)

//	PaintImageAtCursor
//
//	Paints the image for the current element

	{
	if (!IsCursorValid())
		return;

	ICCItem *pItem = m_pList->GetElement(m_iCursor);
	if (pItem->GetCount() <= ICON_INDEX)
		return;

	ICCItem *pIcon = pItem->GetElement(ICON_INDEX);
	if (pIcon->GetCount() < IMAGE_ELEMENTS)
		return;

	CG16bitImage *pImage = g_pUniverse->GetLibraryBitmap(pIcon->GetElement(IMAGE_UNID_INDEX)->GetIntegerValue());
	if (pImage == NULL)
		return;

	Dest.ColorTransBlt(pIcon->GetElement(IMAGE_X_INDEX)->GetIntegerValue(),
			pIcon->GetElement(IMAGE_Y_INDEX)->GetIntegerValue(),
			ICON_WIDTH,
			ICON_HEIGHT,
			255,
			*pImage,
			x,
			y);
	}
예제 #2
0
ICCItem *fnAtmCreate (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnAtmCreate
//
//	Creates a new atom table
//
//	(atmAtomTable ((atom1 entry1) (atom2 entry2) ... (atomn entryn))) -> atmtable

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pAtomTable;
	ICCItem *pList;
	int i;

	//	Evaluate the argument

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l"));
	if (pArgs->IsError())
		return pArgs;

	//	Create the table

	pAtomTable = pCC->CreateAtomTable();
	if (pAtomTable->IsError())
		return pAtomTable;

	//	Add each entry

	pList = pArgs->Head(pCC);
	for (i = 0; i < pList->GetCount(); i++)
		{
		ICCItem *pPair = pList->GetElement(i);
		ICCItem *pResult;

		//	Make sure we have two elements

		if (pPair->GetCount() != 2)
			{
			pAtomTable->Discard(pCC);
			return pCC->CreateError(CONSTLIT("Invalid format for atom table entry:"), pPair);
			}

		//	Get the atom and the entry

		pResult = pAtomTable->AddEntry(pCC, pPair->GetElement(0), pPair->GetElement(1));
		if (pResult->IsError())
			{
			pAtomTable->Discard(pCC);
			return pResult;
			}

		pResult->Discard(pCC);
		}

	//	Done

	pArgs->Discard(pCC);
	return pAtomTable;
	}
예제 #3
0
ICCItem *fnRandom (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnRandom
//
//	(random from to) -> number
//	(random list) -> random item in list

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pResult;

	//	Evaluate the arguments and validate them

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*"));
	if (pArgs->IsError())
		return pArgs;

	//	Do stuff based on parameters

	if (pArgs->GetCount() == 2)
		{
		int iOp1 = pArgs->GetElement(0)->GetIntegerValue();
		int iOp2 = pArgs->GetElement(1)->GetIntegerValue();
		pArgs->Discard(pCC);

		pResult = pCC->CreateInteger(mathRandom(iOp1, iOp2));
		}
	else if (pArgs->GetCount() == 1)
		{
		ICCItem *pList = pArgs->GetElement(0);

		if (pList->IsNil())
			pResult = pCC->CreateNil();
		else if (pList->GetCount() == 0)
			pResult = pCC->CreateNil();
		else
			pResult = pList->GetElement(mathRandom(0, pList->GetCount()-1))->Reference();

		pArgs->Discard(pCC);
		}
	else
		{
		pResult = pCC->CreateNil();
		pArgs->Discard(pCC);
		}

	//	Done

	return pResult;
	}
예제 #4
0
ICCItem *fnShuffle (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnShuffle
//
//	Shuffles a list randomly

	{
	int i;
	CCodeChain *pCC = pCtx->pCC;

	if (pArgs->GetElement(0)->IsNil())
		return pCC->CreateNil();

	//	Create a destination list

	ICCItem *pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		return pResult;

	CCLinkedList *pList = (CCLinkedList *)pResult;

	//	Copy the list

	ICCItem *pSource = pArgs->GetElement(0);
	for (i = 0; i < pSource->GetCount(); i++)
		pList->Append(pCC, pSource->GetElement(i), NULL);

	//	Shuffle the new list

	pList->Shuffle(pCC);

	//	Done

	return pResult;
	}
예제 #5
0
ICCItem *fnAppend (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnAppend
//
//	Appends two or more elements together

	{
	int i, j;
	CCodeChain *pCC = pCtx->pCC;

	//	Create a new list to store the result in

	ICCItem *pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		return pResult;

	CCLinkedList *pList = (CCLinkedList *)pResult;

	//	Loop over all arguments and add to result list

	for (i = 0; i < pArgs->GetCount(); i++)
		{
		ICCItem *pItem = pArgs->GetElement(i);

		for (j = 0; j < pItem->GetCount(); j++)
			pList->Append(pCC, pItem->GetElement(j), NULL);
		}

	//	Done

	return pResult;
	}
예제 #6
0
ICCItem *fnCat (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnCat
//
//	Concatenates the given strings
//
//	(cat string1 string2 ... stringn)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pResult;
	CString sResult;
	int i;

	//	Evaluate the arguments and validate them

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*"));
	if (pArgs->IsError())
		return pArgs;

	//	Append each of the items

	for (i = 0; i < pArgs->GetCount(); i++)
		sResult.Append(pArgs->GetElement(i)->GetStringValue());

	pResult = pCC->CreateString(sResult);

	//	Done

	pArgs->Discard(pCC);
	return pResult;
	}
예제 #7
0
ICCItem *fnCount (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnCount
//
//	Returns the number of elements in the list
//
//	(count list)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pResult;
	ICCItem *pList;

	//	Evaluate the arguments and validate them

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("l"));
	if (pArgs->IsError())
		return pArgs;

	//	The first argument is the list

	pList = pArgs->Head(pCC);
	pResult = pCC->CreateInteger(pList->GetCount());

	//	Done

	pArgs->Discard(pCC);
	return pResult;
	}
예제 #8
0
ICCItem *fnSeededRandom (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnSeededRandom
//
//	(seededRandom seed from to) -> number
//	(seededRandom seed list) -> random item in list

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pResult;

	int iSeed = pArgs->GetElement(0)->GetIntegerValue();

	//	Do stuff based on parameters

	if (pArgs->GetCount() == 3)
		{
		int iOp1 = pArgs->GetElement(1)->GetIntegerValue();
		int iOp2 = pArgs->GetElement(2)->GetIntegerValue();

		pResult = pCC->CreateInteger(mathSeededRandom(iSeed, iOp1, iOp2));
		}
	else if (pArgs->GetCount() == 2)
		{
		ICCItem *pList = pArgs->GetElement(1);

		if (pList->IsNil())
			pResult = pCC->CreateNil();
		else if (pList->GetCount() == 0)
			pResult = pCC->CreateNil();
		else
			pResult = pList->GetElement(mathSeededRandom(iSeed, 0, pList->GetCount()-1))->Reference();
		}
	else
		pResult = pCC->CreateNil();

	//	Done

	return pResult;
	}
예제 #9
0
CString CListWrapper::GetDescAtCursor (void)

//	GetDescAtCursor
//
//	Returns the description of the list element

	{
	if (IsCursorValid())
		{
		ICCItem *pItem = m_pList->GetElement(m_iCursor);
		if (DESC_INDEX < pItem->GetCount())
			return pItem->GetElement(DESC_INDEX)->GetStringValue();
		}

	return NULL_STR;
	}
예제 #10
0
CString CListWrapper::GetTitleAtCursor (void)

//	GetTitleAtCursor
//
//	Returns the title of the list element

	{
	if (IsCursorValid())
		{
		ICCItem *pItem = m_pList->GetElement(m_iCursor);
		if (TITLE_INDEX < pItem->GetCount())
			return pItem->GetElement(TITLE_INDEX)->GetStringValue();
		}

	return NULL_STR;
	}
예제 #11
0
ICCItem *fnFind (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnFind
//
//	Finds a target in a source

	{
	int i;
	CCodeChain *pCC = pCtx->pCC;

	//	Get the source and target

	ICCItem *pSource = pArgs->GetElement(0);
	ICCItem *pTarget = pArgs->GetElement(1);

	//	If this is a list, then look for the target in the list and
	//	return the item position in the list

	int iPos;
	if (pSource->IsList())
		{
		iPos = -1;
		for (i = 0; i < pSource->GetCount(); i++)
			{
			ICCItem *pItem = pSource->GetElement(i);
			if (HelperCompareItems(pItem, pTarget) == 0)
				{
				iPos = i;
				break;
				}
			}
		}

	//	Otherwise, look for the target string in the source string

	else
		{
		iPos = strFind(pSource->GetStringValue(), pTarget->GetStringValue());
		}

	//	Done

	if (iPos == -1)
		return pCC->CreateNil();
	else
		return pCC->CreateInteger(iPos);
	}
예제 #12
0
void CCommandLineDisplay::AutoCompleteSearch (void)

//	AutocompleteSearch
//
//	Searches the global symbol table for matches to the current command.

	{
	const CString sCurCmd = GetCurrentCmd();
	CString sCommon;
	CString sHelp;

	ClearHint();
	if (sCurCmd.IsBlank())
		return;

	//	Get the list of global symbols

	ICCItem *pGlobals = g_pUniverse->GetCC().GetGlobals();

	int iMatches = 0;

	for (int i = 0; i < pGlobals->GetCount(); i++)
		{
		CString sGlobal = pGlobals->GetKey(i);

		//	Partial match
		if (strStartsWith(sGlobal, sCurCmd))
			{
			if (iMatches == 0)
				sCommon = sGlobal;
			//	If we have multiple matching commands then find the longest common stem
			else
				{
				int iLen = min(sCommon.GetLength(), sGlobal.GetLength());
				char *pPos1 = sCommon.GetPointer();
				char *pPos2 = sGlobal.GetPointer();
				int i;
				for (i = 0; i < iLen; i++)
					{
					if (CharLower((LPTSTR)(BYTE)(*pPos1)) != CharLower((LPTSTR)(BYTE)(*pPos2)))
						break;
					pPos1++;
					pPos2++;
					}
				sCommon.Truncate(i);
				m_sHint.Append(CONSTLIT(" "));
				}
			//	Append the command to the auto complete hint
			m_sHint.Append(sGlobal);
			iMatches++;
			}

		if (strEquals(sGlobal, sCurCmd))
			{
			//	Exact match - get help text
			ICCItem *pItem = pGlobals->GetElement(i);
			if (pItem->IsPrimitive())
				sHelp = pItem->GetHelp();
			}
		}

	//	If the common stem is longer than the current command, then auto complete
	if (sCommon.GetLength() > sCurCmd.GetLength())
		Input(strSubString(sCommon, sCurCmd.GetLength(), -1));

	//	If we only have one match then no need to show hint as we have either
	//	auto completed or will show help text insead
	if (iMatches == 1)
		m_sHint = NULL_STR;

	if (!sHelp.IsBlank())
		{
		if (!m_sHint.IsBlank())
			m_sHint.Append(CONSTLIT("\n"));
		m_sHint.Append(sHelp);
		}
	}
예제 #13
0
ICCItem *fnApply (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnApply
//
//	Applies the given parameter list to the lambda expression
//
//	(apply exp arg1 arg2 ... argn list)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pResult;
	ICCItem *pFunction;
	ICCItem *pLast;
	CCLinkedList *pList;
	int i;

	//	Evaluate the arguments and validate them

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("v*"));
	if (pArgs->IsError())
		return pArgs;

	//	We better have at least two arguments

	if (pArgs->GetCount() < 2)
		{
		pArgs->Discard(pCC);
		return pCC->CreateError(CONSTLIT("apply needs a function and a list of arguments."), NULL);
		}

	//	The last argument better be a list

	pLast = pArgs->GetElement(pArgs->GetCount() - 1);
	if (!pLast->IsList())
		{
		pArgs->Discard(pCC);
		return pCC->CreateError(CONSTLIT("Last argument for apply must be a list."), NULL);
		}

	//	The first argument is the function

	pFunction = pArgs->Head(pCC);

	//	Create a new list to store the arguments in

	pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		{
		pArgs->Discard(pCC);
		return pResult;
		}

	pList = (CCLinkedList *)pResult;

	//	Add each of the arguments except the last

	for (i = 1; i < pArgs->GetCount() - 1; i++)
		{
		pList->Append(pCC, pArgs->GetElement(i), &pResult);
		if (pResult->IsError())
			{
			pList->Discard(pCC);
			pArgs->Discard(pCC);
			return pResult;
			}

		pResult->Discard(pCC);
		}

	//	Add each of the elements of the last list

	for (i = 0; i < pLast->GetCount(); i++)
		{
		pList->Append(pCC, pLast->GetElement(i), &pResult);
		if (pResult->IsError())
			{
			pList->Discard(pCC);
			pArgs->Discard(pCC);
			return pResult;
			}

		pResult->Discard(pCC);
		}

	//	Set the literal flag to indicate that the arguments should
	//	not be evaluated.

	pList->SetQuoted();

	//	Execute the function

	if (pFunction->IsFunction())
		pResult = pFunction->Execute(pCtx, pList);
	else
		pResult = pFunction->Reference();

	pList->Discard(pCC);

	//	Done

	pArgs->Discard(pCC);
	return pResult;
	}
예제 #14
0
ICCItem *fnFilter (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnFilter
//
//	Filters a list based on a boolean expression.
//
//	(filter list var exp) -> list

	{
	int i;
	CCodeChain *pCC = pCtx->pCC;

	if (pArgs->GetElement(0)->IsNil())
		return pCC->CreateNil();

	//	Args

	ICCItem *pSource = pArgs->GetElement(0);
	ICCItem *pVar = pArgs->GetElement(1);
	ICCItem *pBody = pArgs->GetElement(2);

	//	Create a destination list

	ICCItem *pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		return pResult;

	CCLinkedList *pList = (CCLinkedList *)pResult;

	//	Setup the locals. We start by creating a local symbol table

	ICCItem *pLocalSymbols = pCC->CreateSymbolTable();
	if (pLocalSymbols->IsError())
		{
		pResult->Discard(pCC);
		return pLocalSymbols;
		}

	//	Associate the enumaration variable

	ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil());
	if (pError->IsError())
		{
		pLocalSymbols->Discard(pCC);
		pResult->Discard(pCC);
		return pError;
		}

	pError->Discard(pCC);

	//	Setup the context

	if (pCtx->pLocalSymbols)
		pLocalSymbols->SetParent(pCtx->pLocalSymbols);
	else
		pLocalSymbols->SetParent(pCtx->pLexicalSymbols);
	ICCItem *pOldSymbols = pCtx->pLocalSymbols;
	pCtx->pLocalSymbols = pLocalSymbols;

	//	Get the offset of the variable so we don't have to
	//	search for it all the time

	int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar);

	//	Loop over all elements of the list

	for (i = 0; i < pSource->GetCount(); i++)
		{
		ICCItem *pItem = pSource->GetElement(i);

		//	Set the element

		pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem);

		//	Eval

		ICCItem *pSelect = pCC->Eval(pCtx, pBody);
		if (pSelect->IsError())
			{
			pResult->Discard(pCC);
			pResult = pSelect;
			break;
			}

		//	If the evaluation is not Nil, then we include the
		//	item in the result

		if (!pSelect->IsNil())
			pList->Append(pCC, pItem, NULL);

		pSelect->Discard(pCC);
		}

	//	Clean up

	pCtx->pLocalSymbols = pOldSymbols;
	pLocalSymbols->Discard(pCC);

	//	Done

	if (pResult->GetCount() > 0)
		return pResult;
	else
		{
		pResult->Discard(pCC);
		return pCC->CreateNil();
		}
	}
예제 #15
0
ICCItem *fnEnum (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnEnum
//
//	Enumerates the elements of a list
//
//	(enum list item-var exp)
//	(enumwhile list condition item-var exp)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pArgs;
	ICCItem *pResult;
	ICCItem *pVar;
	ICCItem *pBody;
	ICCItem *pList;
	ICCItem *pCondition;
	ICCItem *pLocalSymbols;
	ICCItem *pOldSymbols;
	ICCItem *pError;
	int i, iVarOffset;

	//	Evaluate the arguments and validate them

	if (dwData == FN_ENUM_WHILE)
		{
		pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vuqu"));
		if (pArgs->IsError())
			return pArgs;

		pList = pArgs->GetElement(0);
		pCondition = pArgs->GetElement(1);
		pVar = pArgs->GetElement(2);
		pBody = pArgs->GetElement(3);
		}
	else
		{
		pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("vqu"));
		if (pArgs->IsError())
			return pArgs;

		pList = pArgs->GetElement(0);
		pCondition = NULL;
		pVar = pArgs->GetElement(1);
		pBody = pArgs->GetElement(2);
		}

	//	Setup the locals. We start by creating a local symbol table

	pLocalSymbols = pCC->CreateSymbolTable();
	if (pLocalSymbols->IsError())
		{
		pArgs->Discard(pCC);
		return pLocalSymbols;
		}

	//	Associate the enumaration variable

	pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil());
	if (pError->IsError())
		{
		pArgs->Discard(pCC);
		return pError;
		}

	pError->Discard(pCC);

	//	Setup the context

	if (pCtx->pLocalSymbols)
		pLocalSymbols->SetParent(pCtx->pLocalSymbols);
	else
		pLocalSymbols->SetParent(pCtx->pLexicalSymbols);
	pOldSymbols = pCtx->pLocalSymbols;
	pCtx->pLocalSymbols = pLocalSymbols;

	//	Start with a default result

	pResult = pCC->CreateNil();

	//	Get the offset of the variable so we don't have to
	//	search for it all the time

	iVarOffset = pLocalSymbols->FindOffset(pCC, pVar);

	//	Loop over all elements of the list

	for (i = 0; i < pList->GetCount(); i++)
		{
		//	Check the condition

		if (pCondition)
			{
			ICCItem *pEval;

			//	Evaluate the condition

			pEval = pCC->Eval(pCtx, pCondition);
			if (pEval->IsError())
				{
				pResult->Discard(pCC);
				pResult = pEval;
				break;
				}

			//	If the condition is Nil, then we're done

			if (pEval->IsNil())
				{
				pEval->Discard(pCC);
				break;
				}
			}

		ICCItem *pItem = pList->GetElement(i);

		//	Clean up the previous result

		pResult->Discard(pCC);

		//	Set the element

		pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem);

		//	Eval

		pResult = pCC->Eval(pCtx, pBody);
		if (pResult->IsError())
			break;
		}

	//	Clean up

	pCtx->pLocalSymbols = pOldSymbols;
	pLocalSymbols->Discard(pCC);

	//	Done

	pArgs->Discard(pCC);
	return pResult;
	}
예제 #16
0
ICCItem *fnEquality (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnEquality
//
//	Equality and inequality
//
//	(eq exp1 exp2 ... expn)
//	(> exp1 exp2 ... expn)
//	(>= exp1 exp2 ... expn)
//	(< exp1 exp2 ... expn)
//	(<= exp1 exp2 ... expn)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pResult;
	ICCItem *pExp;
	ICCItem *pPrev = NULL;
	ICCItem *pArgs;
	int i;

	//	Evaluate the arguments and validate them

	pArgs = pCC->EvaluateArgs(pCtx, pArguments, CONSTLIT("*"));
	if (pArgs->IsError())
		return pArgs;

	//	Loop over all arguments

	for (i = 0; i < pArgs->GetCount(); i++)
		{
		pExp = pArgs->GetElement(i);
		if (pExp->IsError())
			{
			pExp->Reference();
			pArgs->Discard(pCC);
			return pExp;
			}

		if (pPrev)
			{
			int iResult = HelperCompareItems(pPrev, pExp);
			BOOL bOk;

			switch (dwData)
				{
				case FN_EQUALITY_EQ:
					{
					bOk = (iResult == 0);
					break;
					}

				case FN_EQUALITY_LESSER:
					{
					bOk = (iResult < 0);
					break;
					}

				case FN_EQUALITY_LESSER_EQ:
					{
					bOk = (iResult <= 0);
					break;
					}

				case FN_EQUALITY_GREATER:
					{
					bOk = (iResult > 0);
					break;
					}

				case FN_EQUALITY_GREATER_EQ:
					{
					bOk = (iResult >= 0);
					break;
					}

				default:
					ASSERT(FALSE);
				}

			//	If we don't have a match, return

			if (!bOk)
				{
				pArgs->Discard(pCC);
				return pCC->CreateNil();
				}
			}

		//	Remember the previous element so that we can compare

		pPrev = pExp;
		}

	//	If we get here, then all items are ok

	pArgs->Discard(pCC);
	pResult = pCC->CreateTrue();

	//	Done

	return pResult;
	}
예제 #17
0
bool CWeaponFireDesc::FireOnDamageShields (SDamageCtx &Ctx, int iDevice)

//	FireOnDamageShields
//
//	Fire OnDamageShields event. Returns TRUE if we should skip further shields damage

	{
	SEventHandlerDesc Event;
	if (FindEventHandler(evtOnDamageShields, &Event))
		{
		//	Setup arguments

		CCodeChainCtx CCCtx;

		CItemListManipulator ItemList(Ctx.pObj->GetItemList());
		CShip *pShip = Ctx.pObj->AsShip();
		if (pShip)
			pShip->SetCursorAtDevice(ItemList, iDevice);

		CCCtx.SaveAndDefineSourceVar(Ctx.pObj);
		CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit);
		CCCtx.DefineInteger(CONSTLIT("aDevice"), iDevice);
		CCCtx.DefineItem(CONSTLIT("aDeviceItem"), ItemList.GetItemAtCursor());
		CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause);
		CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj());
		CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL));
		CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos);
		CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection);
		CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage);
		CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType()));
		CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType());

		CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft);
		CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage);
		CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
		if (Ctx.bReflect)
			{
			CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT);
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb);
			}
		else
			{
			CCCtx.DefineNil(CONSTLIT("aShieldReflect"));
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
			}

		ICCItem *pResult = CCCtx.Run(Event);

		//	If we return Nil, then we continue processing

		bool bResult;
		if (pResult->IsNil())
			bResult = false;

		//	If this is an integer, we pass damage to armor

		else if (pResult->IsInteger())
			{
			Ctx.iDamage = pResult->GetIntegerValue();
			bResult = true;
			}

		//	If we return a list, then modify variables

		else if (pResult->IsList())
			{
			//	A single value means we modified the damage to armor

			if (pResult->GetCount() == 1)
				{
				if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT))
					{
					Ctx.bReflect = true;
					Ctx.iAbsorb = Ctx.iDamage;
					Ctx.iShieldDamage = 0;
					}
				else
					{
					Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
					if (Ctx.bReflect)
						{
						Ctx.bReflect = false;
						Ctx.iAbsorb = Ctx.iOriginalAbsorb;
						}
					}
				}

			//	Two values mean we modified both damage to armor and shield damage

			else if (pResult->GetCount() == 2)
				{
				Ctx.bReflect = false;
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue()));
				}

			//	Otherwise, we deal with reflection

			else
				{
				Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT);
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue()));
				}

			//	Proceed with processing

			bResult = false;
			}

		//	If this is the string "reflect" then we reflect

		else if (strEquals(pResult->GetStringValue(), STR_SHIELD_REFLECT))
			{
			Ctx.bReflect = true;
			Ctx.iAbsorb = Ctx.iDamage;
			Ctx.iShieldDamage = 0;
			bResult = false;
			}

		//	Otherwise, error

		else
			{
			Ctx.pObj->ReportEventError(ON_DAMAGE_OVERLAY_EVENT, pResult);
			bResult = true;
			}

		CCCtx.Discard(pResult);

		return bResult;
		}
	else
		return false;
	}
예제 #18
0
void CShieldClass::FireOnShieldDamage (CItemCtx &ItemCtx, SDamageCtx &Ctx)

//	FireOnShieldDamage
//
//	Fire OnShieldDamage

	{
	SEventHandlerDesc Event;
	if (FindEventHandlerShieldClass(evtOnShieldDamage, &Event))
		{
		//	Setup arguments

		CCodeChainCtx CCCtx;
		CCCtx.SaveAndDefineSourceVar(ItemCtx.GetSource());
		CCCtx.SaveAndDefineItemVar(ItemCtx);

		CCCtx.DefineInteger(CONSTLIT("aArmorSeg"), Ctx.iSectHit);
		CCCtx.DefineSpaceObject(CONSTLIT("aCause"), Ctx.pCause);
		CCCtx.DefineSpaceObject(CONSTLIT("aAttacker"), Ctx.Attacker.GetObj());
		CCCtx.DefineSpaceObject(CONSTLIT("aOrderGiver"), (Ctx.Attacker.GetObj() ? Ctx.Attacker.GetObj()->GetOrderGiver(Ctx.Attacker.GetCause()) : NULL));
		CCCtx.DefineVector(CONSTLIT("aHitPos"), Ctx.vHitPos);
		CCCtx.DefineInteger(CONSTLIT("aHitDir"), Ctx.iDirection);
		CCCtx.DefineInteger(CONSTLIT("aDamageHP"), Ctx.iDamage);
		CCCtx.DefineString(CONSTLIT("aDamageType"), GetDamageShortName(Ctx.Damage.GetDamageType()));
		CCCtx.DefineItemType(CONSTLIT("aWeaponType"), Ctx.pDesc->GetWeaponType());

		CCCtx.DefineInteger(CONSTLIT("aShieldHP"), Ctx.iHPLeft);
		CCCtx.DefineInteger(CONSTLIT("aShieldDamageHP"), Ctx.iShieldDamage);
		CCCtx.DefineInteger(CONSTLIT("aArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
		if (Ctx.bReflect)
			{
			CCCtx.DefineString(CONSTLIT("aShieldReflect"), STR_SHIELD_REFLECT);
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iOriginalShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iOriginalAbsorb);
			}
		else
			{
			CCCtx.DefineNil(CONSTLIT("aShieldReflect"));
			CCCtx.DefineInteger(CONSTLIT("aOriginalShieldDamageHP"), Ctx.iShieldDamage);
			CCCtx.DefineInteger(CONSTLIT("aOriginalArmorDamageHP"), Ctx.iDamage - Ctx.iAbsorb);
			}

		ICCItem *pResult = CCCtx.Run(Event);

		//	If we return Nil, then nothing

		if (pResult->IsNil())
			NULL;

		//	If an error, report it

		else if (pResult->IsError())
			ItemCtx.GetSource()->ReportEventError(ON_SHIELD_DAMAGE_EVENT, pResult);

		//	If we return a list, then modify variables

		else if (pResult->IsList())
			{
			//	A single value means we modified the damage to armor

			if (pResult->GetCount() == 1)
				{
				if (strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT))
					{
					Ctx.bReflect = true;
					Ctx.iAbsorb = Ctx.iDamage;
					Ctx.iShieldDamage = 0;
					}
				else
					{
					Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
					if (Ctx.bReflect)
						{
						Ctx.bReflect = false;
						Ctx.iAbsorb = Ctx.iOriginalAbsorb;
						}
					}
				}

			//	Two values mean we modified both damage to armor and shield damage

			else if (pResult->GetCount() == 2)
				{
				Ctx.bReflect = false;
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(0)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(1)->GetIntegerValue()));
				}

			//	Otherwise, we deal with reflection

			else
				{
				Ctx.bReflect = strEquals(pResult->GetElement(0)->GetStringValue(), STR_SHIELD_REFLECT);
				Ctx.iShieldDamage = Max(0, Min(pResult->GetElement(1)->GetIntegerValue(), Ctx.iHPLeft));
				Ctx.iAbsorb = Max(0, Ctx.iDamage - Max(0, pResult->GetElement(2)->GetIntegerValue()));
				}
			}

		CCCtx.Discard(pResult);
		}
	}
예제 #19
0
ICCItem *fnPageGet (CEvalContext *pEvalCtx, ICCItem *pArgs, DWORD dwData)

//	fnPageGet
//
//	(pageGet address|pageID enumMethod [startIndex] [count]) -> list

	{
	CCodeChain *pCC = pEvalCtx->pCC;

	//	Args

	ICCItem *pAddress = pArgs->GetElement(0);
	ICCItem *pMethod = pArgs->GetElement(1);
	int iStart = (pArgs->GetCount() > 2 ? pArgs->GetElement(2)->GetIntegerValue() : 0);
	int iCount = (pArgs->GetCount() > 3 ? pArgs->GetElement(3)->GetIntegerValue() : -1);

	//	Open the page

	IPage *pPage;
	CString sError;
	if (g_PM.OpenPage(pAddress->GetStringValue(), &pPage, &sError) != NOERROR)
		return pCC->CreateError(sError, NULL);

	//	Prepare the method

	SPageEnumCtx EnumCtx;
	if (pPage->EnumReset(*pCC, pMethod, EnumCtx, &sError))
		{
		g_PM.ClosePage(pPage);
		return pCC->CreateError(sError, NULL);
		}

	//	Create a destination list

	ICCItem *pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		{
		g_PM.ClosePage(pPage);
		return pResult;
		}

	CCLinkedList *pList = (CCLinkedList *)pResult;

	//	Enumerate the page

	while ((iCount == -1 || iCount > 0) && pPage->EnumHasMore(EnumCtx))
		{
		ICCItem *pItem = pPage->EnumGetNext(*pCC, EnumCtx);
		if (pItem->IsError())
			{
			pResult->Discard(pCC);
			pResult = pItem;
			break;
			}

		//	Add to list

		if (iStart == 0)
			{
			pList->Append(*pCC, pItem);
			iCount--;
			}
		else
			iStart--;

		pItem->Discard(pCC);
		}

	//	Clean up

	g_PM.ClosePage(pPage);

	//	Done

	if (pResult->GetCount() > 0)
		return pResult;
	else
		{
		pResult->Discard(pCC);
		return pCC->CreateNil();
		}
	}
예제 #20
0
ICCItem *fnBlock (CEvalContext *pCtx, ICCItem *pArguments, DWORD dwData)

//	fnBlock
//
//	Evaluates a list of expressions
//
//	(block (locals ...) exp1 exp2 ... expn)
//	(errblock (error locals ...) exp1 exp2 ... expn onerror)

	{
	CCodeChain *pCC = pCtx->pCC;
	ICCItem *pResult;
	ICCItem *pLocals;
	ICCItem *pExp;
	ICCItem *pLocalSymbols;
	ICCItem *pVar;
	ICCItem *pOldSymbols;
	int i;

	//	The first argument must be a list of locals

	pLocals = pArguments->Head(pCC);
	if (pLocals == NULL || !pLocals->IsList())
		return pCC->CreateError(CONSTLIT("Locals list expected:"), pLocals);

	//	If this is an error block then we must have at least one local

	if (dwData == FN_BLOCK_ERRBLOCK && pLocals->GetCount() == 0)
		return pCC->CreateError(CONSTLIT("errblock must have an 'error' local variable"), NULL);

	//	Now loop over the remaining arguments, evaluating each in turn

	pExp = pArguments->GetElement(1);

	//	If there are no expressions, then we just return Nil

	if (pExp == NULL)
		return pCC->CreateNil();

	//	Setup the locals. We start by creating a local symbol table

	pLocalSymbols = pCC->CreateSymbolTable();
	if (pLocalSymbols->IsError())
		return pLocalSymbols;

	pLocalSymbols->SetLocalFrame();

	//	Loop over each item and associate it

	for (i = 0; i < pLocals->GetCount(); i++)
		{
		ICCItem *pItem;

		pVar = pLocals->GetElement(i);

		pItem = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil());
		if (pItem->IsError())
			{
			pLocalSymbols->Discard(pCC);
			return pItem;
			}

		pItem->Discard(pCC);
		}

	//	Setup the context

	if (pCtx->pLocalSymbols)
		pLocalSymbols->SetParent(pCtx->pLocalSymbols);
	else
		pLocalSymbols->SetParent(pCtx->pLexicalSymbols);
	pOldSymbols = pCtx->pLocalSymbols;
	pCtx->pLocalSymbols = pLocalSymbols;

	//	Start with a default result

	pResult = pCC->CreateNil();

	//	Loop (starting with the second arg)

	for (i = 1; i < pArguments->GetCount(); i++)
		{
		pExp = pArguments->GetElement(i);

		//	If this is an error block and this is the last expression,
		//	then it must be error condition and we don't want to 
		//	execute it.

		if (i+1 == pArguments->GetCount() && dwData == FN_BLOCK_ERRBLOCK)
			break;

		//	Evaluate the expression

		pResult->Discard(pCC);
		pResult = pCC->Eval(pCtx, pExp);

		//	If we got an error, handle it

		if (pResult->IsError())
			{
			//	If this is an error block, then find the last expression
			//	and evaluate it.

			if (dwData == FN_BLOCK_ERRBLOCK)
				{
				ICCItem *pItem;

				//	Set the first local variable to be the error result

				pVar = pLocals->Head(pCC);
				pItem = pLocalSymbols->AddEntry(pCC, pVar, pResult);

				pItem->Discard(pCC);
				pResult->Discard(pCC);

				//	Find the last expression

				pExp = pArguments->GetElement(pArguments->GetCount() - 1);

				//	Evaluate it

				pResult = pCC->Eval(pCtx, pExp);
				}

			//	Regardless, leave the block and return the result

			break;
			}
		}

	//	Clean up

	pCtx->pLocalSymbols = pOldSymbols;
	pLocalSymbols->Discard(pCC);

	//	Done

	return pResult;
	}
예제 #21
0
ICCItem *fnPageMap (CEvalContext *pEvalCtx, ICCItem *pArgs, DWORD dwData)

//	fnPageMap
//
//	(pageMap address|pageID enumMethod ['excludeNil] var exp) -> filtered list

	{
	CCodeChain *pCC = pEvalCtx->pCC;

	//	Args

	ICCItem *pAddress = pArgs->GetElement(0);
	ICCItem *pMethod = pArgs->GetElement(1);

	bool bExcludeNil;
	int iOptionalArg = 2;
	if (pArgs->GetCount() > 4)
		bExcludeNil = strEquals(pArgs->GetElement(iOptionalArg++)->GetStringValue(), CONSTLIT("excludeNil"));
	else
		bExcludeNil = false;

	ICCItem *pVar = pArgs->GetElement(iOptionalArg++);
	ICCItem *pBody = pArgs->GetElement(iOptionalArg++);

	//	Open the page

	IPage *pPage;
	CString sError;
	if (g_PM.OpenPage(pAddress->GetStringValue(), &pPage, &sError) != NOERROR)
		return pCC->CreateError(sError, NULL);

	//	Prepare the method

	SPageEnumCtx EnumCtx;
	if (pPage->EnumReset(*pCC, pMethod, EnumCtx, &sError))
		{
		g_PM.ClosePage(pPage);
		return pCC->CreateError(sError, NULL);
		}

	//	Create a destination list

	ICCItem *pResult = pCC->CreateLinkedList();
	if (pResult->IsError())
		{
		g_PM.ClosePage(pPage);
		return pResult;
		}

	CCLinkedList *pList = (CCLinkedList *)pResult;

	//	Setup the locals. We start by creating a local symbol table

	ICCItem *pLocalSymbols = pCC->CreateSymbolTable();
	if (pLocalSymbols->IsError())
		{
		pResult->Discard(pCC);
		g_PM.ClosePage(pPage);
		return pLocalSymbols;
		}

	//	Associate the enumaration variable

	ICCItem *pError = pLocalSymbols->AddEntry(pCC, pVar, pCC->CreateNil());
	if (pError->IsError())
		{
		pLocalSymbols->Discard(pCC);
		pResult->Discard(pCC);
		g_PM.ClosePage(pPage);
		return pError;
		}

	pError->Discard(pCC);

	//	Setup the context

	if (pEvalCtx->pLocalSymbols)
		pLocalSymbols->SetParent(pEvalCtx->pLocalSymbols);
	else
		pLocalSymbols->SetParent(pEvalCtx->pLexicalSymbols);
	ICCItem *pOldSymbols = pEvalCtx->pLocalSymbols;
	pEvalCtx->pLocalSymbols = pLocalSymbols;

	//	Get the offset of the variable so we don't have to
	//	search for it all the time

	int iVarOffset = pLocalSymbols->FindOffset(pCC, pVar);

	//	Enumerate the page

	while (pPage->EnumHasMore(EnumCtx))
		{
		ICCItem *pItem = pPage->EnumGetNext(*pCC, EnumCtx);
		if (pItem->IsError())
			{
			pResult->Discard(pCC);
			pResult = pItem;
			break;
			}

		//	Set the element

		pLocalSymbols->AddByOffset(pCC, iVarOffset, pItem);

		//	Eval

		ICCItem *pMapped = pCC->Eval(pEvalCtx, pBody);
		if (pMapped->IsError())
			{
			pItem->Discard(pCC);
			pResult->Discard(pCC);
			pResult = pMapped;
			break;
			}

		//	If the evaluation is not Nil, then we include the
		//	item in the result

		if (!bExcludeNil || !pMapped->IsNil())
			pList->Append(*pCC, pMapped);

		pItem->Discard(pCC);
		pMapped->Discard(pCC);
		}

	//	Clean up

	pEvalCtx->pLocalSymbols = pOldSymbols;
	pLocalSymbols->Discard(pCC);
	g_PM.ClosePage(pPage);

	//	Done

	if (pResult->GetCount() > 0)
		return pResult;
	else
		{
		pResult->Discard(pCC);
		return pCC->CreateNil();
		}
	}
CLanguageDataBlock::ETranslateResult CLanguageDataBlock::Translate (CSpaceObject *pObj, const CString &sID, TArray<CString> *retText, CString *retsText) const

//	Translate
//
//	Translates an entry to either a string or an array of strings.

	{
	int i;

	//	If we can't find this ID then we can't translate

	SEntry *pEntry = m_Data.GetAt(sID);
	if (pEntry == NULL)
		return resultNotFound;

	//	If we don't want the text back then all we need to do is return that we
	//	have the text.

	if (retText == NULL && retsText == NULL)
		return resultFound;

	//	If we don't need to run code then we just return the string.

	if (pEntry->pCode == NULL)
		{
		if (retsText)
			{
			*retsText = ::ComposePlayerNameString(pEntry->sText, g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome());
			return resultString;
			}
		else
			return resultFound;
		}

	//	Otherwise we have to run some code

	CCodeChainCtx Ctx;
	Ctx.SaveAndDefineSourceVar(pObj);
	Ctx.DefineString(CONSTLIT("aTextID"), sID);
	
	ICCItem *pResult = Ctx.Run(pEntry->pCode);	//	LATER:Event
	ETranslateResult iResult;

	//	Nil

	if (pResult->IsNil())
		iResult = resultNotFound;

	//	List of strings

	else if (pResult->GetCount() > 1)
		{
		if (retText)
			{
			CString sPlayerName = g_pUniverse->GetPlayerName();
			GenomeTypes iPlayerGenome = g_pUniverse->GetPlayerGenome();

			retText->DeleteAll();

			retText->InsertEmpty(pResult->GetCount());
			for (i = 0; i < pResult->GetCount(); i++)
				retText->GetAt(i) = ::ComposePlayerNameString(pResult->GetElement(i)->GetStringValue(), sPlayerName, iPlayerGenome);

			iResult = resultArray;
			}
		else
			iResult = resultFound;
		}

	//	String

	else
		{
		if (retsText)
			{
			*retsText = ::ComposePlayerNameString(pResult->GetStringValue(), g_pUniverse->GetPlayerName(), g_pUniverse->GetPlayerGenome());
			iResult = resultString;
			}
		else
			iResult = resultFound;
		}

	//	Done

	Ctx.Discard(pResult);

	return iResult;
	}
예제 #23
0
ICCItem *fnMathList (CEvalContext *pCtx, ICCItem *pArgs, DWORD dwData)

//	fnMathList
//
//	Simple integer functions
//
//	(add x1 x2 ... xn) -> z
//	(max x1 x2 ... xn) -> z
//	(min x1 x2 ... xn) -> z
//	(multiply x1 x2 .. .xn) -> z

	{
	int i;
	CCodeChain *pCC = pCtx->pCC;

	//	Get the list

	ICCItem *pList;
	if (pArgs->GetElement(0)->IsList())
		{
		pList = pArgs->GetElement(0);

		if (pList->GetCount() < 1)
			return pCC->CreateNil();
		}
	else
		pList = pArgs;

	//	Do the computation

	switch (dwData)
		{
		case FN_MATH_ADD:
			{
			int iResult = pList->GetElement(0)->GetIntegerValue();
			for (i = 1; i < pList->GetCount(); i++)
				iResult += pList->GetElement(i)->GetIntegerValue();
			return pCC->CreateInteger(iResult);
			}

		case FN_MATH_MULTIPLY:
			{
			int iResult = pList->GetElement(0)->GetIntegerValue();
			for (i = 1; i < pList->GetCount(); i++)
				iResult *= pList->GetElement(i)->GetIntegerValue();
			return pCC->CreateInteger(iResult);
			}

		case FN_MATH_MAX:
			{
			int iResult = pList->GetElement(0)->GetIntegerValue();
			for (i = 1; i < pList->GetCount(); i++)
				{
				int iVal = pList->GetElement(i)->GetIntegerValue();
				if (iVal > iResult)
					iResult = iVal;
				}
			return pCC->CreateInteger(iResult);
			}

		case FN_MATH_MIN:
			{
			int iResult = pList->GetElement(0)->GetIntegerValue();
			for (i = 1; i < pList->GetCount(); i++)
				{
				int iVal = pList->GetElement(i)->GetIntegerValue();
				if (iVal < iResult)
					iResult = iVal;
				}
			return pCC->CreateInteger(iResult);
			}

		default:
			ASSERT(false);
			return pCC->CreateNil();
		}
	}