示例#1
0
void C4Effect::Kill()
{
	// active?
	C4Effect *pLastRemovedEffect=NULL;
	if (IsActive())
		// then temp remove all higher priority effects
		TempRemoveUpperEffects(false, &pLastRemovedEffect);
	else
		// otherwise: temp reactivate before real removal
		// this happens only if a lower priority effect removes an upper priority effect in its add- or removal-call
		if (iPriority!=1) CallStart(C4FxCall_TempAddForRemoval, C4Value(), C4Value(), C4Value(), C4Value());
	// remove this effect
	int32_t iPrevPrio = iPriority; SetDead();
	if (CallStop(C4FxCall_Normal, false) == C4Fx_Stop_Deny)
		// effect denied to be removed: recover
		iPriority = iPrevPrio;
	// reactivate other effects
	TempReaddUpperEffects(pLastRemovedEffect);
	// Update OnFire cache
	if (Target && WildcardMatch(C4Fx_AnyFire, GetName()))
		if (!Get(C4Fx_AnyFire))
			Target->SetOnFire(false);
	if (IsDead() && !GetCallbackScript())
		Call(P_Destruction, &C4AulParSet(C4FxCall_Normal));
}
示例#2
0
C4Value C4PropList::Call(C4String * k, C4AulParSet *Pars, bool fPassErrors)
{
	if (!Status) return C4Value();
	C4AulFunc *pFn = GetFunc(k);
	if (!pFn) return C4Value();
	return pFn->Exec(this, Pars, fPassErrors);
}
示例#3
0
C4Value C4PropList::Call(const char * s, C4AulParSet *Pars, bool fPassErrors)
{
	if (!Status) return C4Value();
	assert(s && s[0]);
	C4AulFunc *pFn = GetFunc(s);
	if (!pFn) return C4Value();
	return pFn->Exec(this, Pars, fPassErrors);
}
示例#4
0
C4Value C4Effect::DoCall(C4Object *pObj, const char *szFn, C4Value &rVal1,
                         C4Value &rVal2, C4Value &rVal3, C4Value &rVal4,
                         C4Value &rVal5, C4Value &rVal6, C4Value &rVal7) {
  // def script or global only?
  C4AulScript *pSrcScript;
  C4Def *pDef;
  if (pCommandTarget) {
    pSrcScript = &pCommandTarget->Def->Script;
    // overwrite ID for sync safety in runtime join
    idCommandTarget = pCommandTarget->id;
  } else if (idCommandTarget && (pDef = Game.Defs.ID2Def(idCommandTarget)))
    pSrcScript = &pDef->Script;
  else
    pSrcScript = &Game.ScriptEngine;
  // compose function name
  char fn[C4AUL_MAX_Identifier + 1];
  sprintf(fn, PSF_FxCustom, Name, szFn);
  // call it
  C4AulFunc *pFn = pSrcScript->GetFuncRecursive(fn);
  if (!pFn)
    return C4Value();
  return pFn->Exec(pCommandTarget,
                   &C4AulParSet(C4VObj(pObj), C4VInt(iNumber), rVal1, rVal2,
                                rVal3, rVal4, rVal5, rVal6, rVal7));
}
TEST(DirectExecTest, SanityTests)
{
	C4AulScript * pScript = new C4AulScript();
	ASSERT_TRUE(pScript);
	C4Value rVal(pScript->DirectExec(nullptr, "5*8", "unit test script", false, nullptr));
	EXPECT_EQ(rVal, C4Value(5*8));
	delete pScript;
}
示例#6
0
C4SortObject *C4SortObject::CreateByValue(const C4Value &DataVal) {
  // Must be an array
  const C4ValueArray *pArray = C4Value(DataVal).getArray();
  if (!pArray) return NULL;
  const C4ValueArray &Data = *pArray;
  int32_t iType = Data[0].getInt();
  return CreateByValue(iType, Data);
}
示例#7
0
void C4Effect::TempReaddUpperEffects(C4Effect *pLastReaddEffect)
{
	// nothing to do? - this will also happen if TempRemoveUpperEffects did nothing due to priority==1
	if (!pLastReaddEffect) return;
	if (Target && !Target->Status) return; // this will be invalid!
	// simply activate all following, inactive effects
	for (C4Effect *pEff = pNext; pEff; pEff = pEff->pNext)
	{
		if (pEff->IsInactiveAndNotDead())
		{
			pEff->FlipActive();
			if (pEff->iPriority!=1) pEff->CallStart(C4FxCall_Temp, C4Value(), C4Value(), C4Value(), C4Value());
			if (Target && WildcardMatch(C4Fx_AnyFire, pEff->GetName()))
				Target->SetOnFire(true);
		}
		// done?
		if (pEff == pLastReaddEffect) break;
	}
}
示例#8
0
TEST_F(AulTest, Loops)
{
	EXPECT_EQ(C4VInt(5), RunCode("var i = 0; do ++i; while (i < 5); return i;"));
	EXPECT_EQ(C4VInt(5), RunCode("var i = 0; while (i < 5) ++i; return i;"));
	EXPECT_EQ(C4VInt(5), RunCode("for(var i = 0; i < 5; ++i); return i;"));
	EXPECT_EQ(C4VInt(6), RunCode("var i = 0, b; do { b = i++ >= 5; } while (!b); return i;"));
	EXPECT_EQ(C4VInt(6), RunCode("var i = 0, b; while (!b) { b = i++ >= 5; } return i;"));
	EXPECT_EQ(C4Value(), RunCode("var a = [], sum; for(var i in a) sum += i; return sum;"));
	EXPECT_EQ(C4VInt(1), RunCode("var a = [1], sum; for(var i in a) sum += i; return sum;"));
	EXPECT_EQ(C4VInt(6), RunCode("var a = [1,2,3], sum; for(var i in a) sum += i; return sum;"));
}
示例#9
0
int32_t C4Effect::Check(C4Object *pForObj, const char *szCheckEffect,
                        int32_t iPrio, int32_t iTimer, C4Value &rVal1,
                        C4Value &rVal2, C4Value &rVal3, C4Value &rVal4) {
  // priority=1: always OK; no callbacks
  if (iPrio == 1)
    return 0;
  // check this and other effects
  C4Effect *pAddToEffect = NULL;
  bool fDoTempCallsForAdd = false;
  C4Effect *pLastRemovedEffect = NULL;
  for (C4Effect *pCheck = this; pCheck; pCheck = pCheck->pNext) {
    if (!pCheck->IsDead() && pCheck->pFnEffect && pCheck->iPriority >= iPrio) {
      int32_t iResult =
          pCheck->pFnEffect->Exec(pCheck->pCommandTarget,
                                  &C4AulParSet(C4VString(szCheckEffect),
                                               C4VObj(pForObj),
                                               C4VInt(pCheck->iNumber),
                                               C4Value(), rVal1, rVal2, rVal3,
                                               rVal4)).getInt();
      if (iResult == C4Fx_Effect_Deny)
        // effect denied
        return C4Fx_Effect_Deny;
      // add to other effect
      if (iResult == C4Fx_Effect_Annul || iResult == C4Fx_Effect_AnnulCalls) {
        pAddToEffect = pCheck;
        fDoTempCallsForAdd = (iResult == C4Fx_Effect_AnnulCalls);
      }
    }
  }
  // adding to other effect?
  if (pAddToEffect) {
    // do temp remove calls if desired
    if (pAddToEffect->pNext && fDoTempCallsForAdd)
      pAddToEffect->TempRemoveUpperEffects(pForObj, false, &pLastRemovedEffect);
    C4Value Par1 = C4VString(szCheckEffect), Par2 = C4VInt(iTimer), Par8;
    int32_t iResult =
        pAddToEffect->DoCall(pForObj, PSFS_FxAdd, Par1, Par2, rVal1, rVal2,
                             rVal3, rVal4, Par8).getInt();
    // do temp readd calls if desired
    if (pAddToEffect->pNext && fDoTempCallsForAdd)
      pAddToEffect->TempReaddUpperEffects(pForObj, pLastRemovedEffect);
    // effect removed by this call?
    if (iResult == C4Fx_Start_Deny) {
      pAddToEffect->Kill(pForObj);
      return C4Fx_Effect_Annul;
    } else
      // other effect is the target effect number
      return pAddToEffect->iNumber;
  }
  // added to no effect and not denied
  return 0;
}
示例#10
0
TEST_F(AulTest, ValueReturn)
{
	// Make sure primitive value returns work.
	EXPECT_EQ(C4VNull, RunCode("return;"));
	EXPECT_EQ(C4VNull, RunExpr("nil"));
	EXPECT_EQ(C4Value(true), RunExpr("true"));
	EXPECT_EQ(C4Value(false), RunExpr("false"));
	EXPECT_EQ(C4VInt(42), RunExpr("42"));
	EXPECT_EQ(C4VString("Hello World!"), RunExpr("\"Hello World!\""));

	// Make sure array returns work.
	EXPECT_EQ(C4VArray(), RunExpr("[]"));
	EXPECT_EQ(
		C4VArray(C4VInt(0), C4VNull, C4VArray(C4VInt(1)), C4VString("Hi")),
		RunExpr("[0, nil, [1], \"Hi\"]"));

	// Make sure proplist returns work.
	EXPECT_EQ(C4VPropList(), RunExpr("{}"));
	EXPECT_EQ(
		C4VPropList("a", C4VInt(1), "b", C4VArray()),
		RunExpr("{\"a\": 1, \"b\"=[]}"));
}
示例#11
0
void C4ValueArray::CompileFunc(class StdCompiler *pComp, C4ValueNumbers * numbers)
{
	int32_t inSize = iSize;
	// Size. Reset if not found.
	try
		{ pComp->Value(inSize); }
	catch (StdCompiler::NotFoundException *pExc)
		{ Reset(); delete pExc; return; }
	// Separator
	pComp->Separator(StdCompiler::SEP_SEP2);
	// Allocate
	if (pComp->isCompiler()) this->SetSize(inSize);
	// Values
	pComp->Value(mkArrayAdaptMap(pData, iSize, C4Value(), mkParAdaptMaker(numbers)));
}
示例#12
0
bool C4Effect::GetPropertyByS(C4String *k, C4Value *pResult) const
{
	if (k >= &Strings.P[0] && k < &Strings.P[P_LAST])
	{
		switch(k - &Strings.P[0])
		{
			case P_Name: return C4PropListNumbered::GetPropertyByS(k, pResult);
			case P_Priority: *pResult = C4VInt(Abs(iPriority)); return true;
			case P_Interval: *pResult = C4VInt(iInterval); return true;
			case P_CommandTarget: *pResult = CommandTarget; return true;
			case P_Target: *pResult = C4Value(Target); return true;
			case P_Time: *pResult = C4VInt(iTime); return true;
		}
	}
	return C4PropListNumbered::GetPropertyByS(k, pResult);
}
示例#13
0
C4Value C4Effect::DoCall(C4PropList *pObj, const char *szFn, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4, const C4Value &rVal5, const C4Value &rVal6, const C4Value &rVal7)
{
	C4PropList * p = GetCallbackScript();
	if (!p)
	{
		C4AulFunc * fn = GetFunc(szFn);
		if (fn) return fn->Exec(this, &C4AulParSet(rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7));
	}
	else
	{
		// old variant
		// compose function name
		C4AulFunc * fn = p->GetFunc(FormatString(PSF_FxCustom, GetName(), szFn).getData());
		if (fn) return fn->Exec(p, &C4AulParSet(Obj(pObj), this, rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7));
	}
	return C4Value();
}
void C4ScenarioParameterDefs::RegisterScriptConstants(const C4ScenarioParameters &values)
{
	// register constants for all parameters in script engine

	// old-style: one constant per parameter
	for (const auto & Parameter : Parameters)
	{
		StdStrBuf constant_name;
		constant_name.Format("SCENPAR_%s", Parameter.GetID());
		int32_t constant_value = values.GetValueByID(Parameter.GetID(), Parameter.GetDefault());
		::ScriptEngine.RegisterGlobalConstant(constant_name.getData(), C4VInt(constant_value));
	}

	// new-style: all constants in a proplist
	auto scenpar = C4PropList::NewStatic(nullptr, nullptr, &Strings.P[P_SCENPAR]);
	for (const auto & Parameter : Parameters)
	{
		int32_t constant_value = values.GetValueByID(Parameter.GetID(), Parameter.GetDefault());
		scenpar->SetPropertyByS(Strings.RegString(StdStrBuf(Parameter.GetID())), C4VInt(constant_value));
	}
	scenpar->Freeze();
	::ScriptEngine.RegisterGlobalConstant("SCENPAR", C4Value(scenpar));
}
示例#15
0
C4FindObject *C4FindObject::CreateByValue(const C4Value &DataVal,
                                          C4SortObject **ppSortObj) {
  // Must be an array
  C4ValueArray *pArray = C4Value(DataVal).getArray();
  if (!pArray) return NULL;

  const C4ValueArray &Data = *pArray;
  int32_t iType = Data[0].getInt();
  if (Inside<int32_t>(iType, C4SO_First, C4SO_Last)) {
    // this is not a FindObject but a sort condition!
    // sort condition not desired here?
    if (!ppSortObj) return NULL;
    // otherwise, create it!
    *ppSortObj = C4SortObject::CreateByValue(iType, Data);
    // done
    return NULL;
  }

  switch (iType) {
    case C4FO_Not: {
      // Create child condition
      C4FindObject *pCond = C4FindObject::CreateByValue(Data[1]);
      if (!pCond) return NULL;
      // wrap
      return new C4FindObjectNot(pCond);
    }

    case C4FO_And:
    case C4FO_Or: {
      // Trivial case (one condition)
      if (Data.GetSize() == 2) return C4FindObject::CreateByValue(Data[1]);
      // Create all childs
      int32_t i;
      C4FindObject **ppConds = new C4FindObject *[Data.GetSize() - 1];
      for (i = 0; i < Data.GetSize() - 1; i++)
        ppConds[i] = C4FindObject::CreateByValue(Data[i + 1]);
      // Count real entries, move them to start of list
      int32_t iSize = 0;
      for (i = 0; i < Data.GetSize() - 1; i++)
        if (ppConds[i])
          if (iSize++ != i) ppConds[iSize - 1] = ppConds[i];
      // Create
      if (iType == C4FO_And)
        return new C4FindObjectAnd(iSize, ppConds);
      else
        return new C4FindObjectOr(iSize, ppConds);
    }

    case C4FO_Exclude:
      return new C4FindObjectExclude(Data[1].getObj());

    case C4FO_ID:
      return new C4FindObjectID(Data[1].getC4ID());

    case C4FO_InRect:
      return new C4FindObjectInRect(C4Rect(Data[1].getInt(), Data[2].getInt(),
                                           Data[3].getInt(), Data[4].getInt()));

    case C4FO_AtPoint:
      return new C4FindObjectAtPoint(Data[1].getInt(), Data[2].getInt());

    case C4FO_AtRect:
      return new C4FindObjectAtRect(Data[1].getInt(), Data[2].getInt(),
                                    Data[3].getInt(), Data[4].getInt());

    case C4FO_OnLine:
      return new C4FindObjectOnLine(Data[1].getInt(), Data[2].getInt(),
                                    Data[3].getInt(), Data[4].getInt());

    case C4FO_Distance:
      return new C4FindObjectDistance(Data[1].getInt(), Data[2].getInt(),
                                      Data[3].getInt());

    case C4FO_OCF:
      return new C4FindObjectOCF(Data[1].getInt());

    case C4FO_Category:
      return new C4FindObjectCategory(Data[1].getInt());

    case C4FO_Action: {
      C4String *pStr = Data[1].getStr();
      if (!pStr) return NULL;
      // Don't copy, it should be safe
      return new C4FindObjectAction(pStr->Data.getData());
    }

    case C4FO_Func: {
      // Get function name
      C4String *pStr = Data[1].getStr();
      if (!pStr) return NULL;
      // Construct
      C4FindObjectFunc *pFO = new C4FindObjectFunc(pStr->Data.getData());
      // Add parameters
      for (int i = 2; i < Data.GetSize(); i++) pFO->SetPar(i - 2, Data[i]);
      // Done
      return pFO;
    }

    case C4FO_ActionTarget: {
      int index = 0;
      if (Data.GetSize() >= 3) index = BoundBy(Data[2].getInt(), 0, 1);
      return new C4FindObjectActionTarget(Data[1].getObj(), index);
    }

    case C4FO_Container:
      return new C4FindObjectContainer(Data[1].getObj());

    case C4FO_AnyContainer:
      return new C4FindObjectAnyContainer();

    case C4FO_Owner:
      return new C4FindObjectOwner(Data[1].getInt());

    case C4FO_Controller:
      return new C4FindObjectController(Data[1].getInt());

    case C4FO_Layer:
      return new C4FindObjectLayer(Data[1].getObj());
  }
  return NULL;
}
示例#16
0
C4FindObject *C4FindObject::CreateByValue(const C4Value &DataVal, C4SortObject **ppSortObj, const C4Object *context, bool *has_layer_check)
{
	// Must be an array
	C4ValueArray *pArray = C4Value(DataVal).getArray();
	if (!pArray) return NULL;

	const C4ValueArray &Data = *pArray;
	int32_t iType = Data[0].getInt();
	if (Inside<int32_t>(iType, C4SO_First, C4SO_Last))
	{
		// this is not a FindObject but a sort condition!
		// sort condition not desired here?
		if (!ppSortObj) return NULL;
		// otherwise, create it!
		*ppSortObj = C4SortObject::CreateByValue(iType, Data, context);
		// done
		return NULL;
	}

	switch (iType)
	{
	case C4FO_Not:
	{
		// Create child condition
		C4FindObject *pCond = C4FindObject::CreateByValue(Data[1], nullptr, context, has_layer_check);
		if (!pCond) return NULL;
		// wrap
		return new C4FindObjectNot(pCond);
	}

	case C4FO_And: case C4FO_Or:
	{
		// Trivial case (one condition)
		if (Data.GetSize() == 2)
			return C4FindObject::CreateByValue(Data[1], nullptr, context, has_layer_check);
		// Create all childs
		int32_t i;
		C4FindObject **ppConds = new C4FindObject *[Data.GetSize() - 1];
		for (i = 0; i < Data.GetSize() - 1; i++)
			ppConds[i] = C4FindObject::CreateByValue(Data[i + 1], nullptr, context, has_layer_check);
		// Count real entries, move them to start of list
		int32_t iSize = 0;
		for (i = 0; i < Data.GetSize() - 1; i++)
			if (ppConds[i])
				if (iSize++ != i)
					ppConds[iSize-1] = ppConds[i];
		// Create
		if (iType == C4FO_And)
			return new C4FindObjectAnd(iSize, ppConds);
		else
			return new C4FindObjectOr(iSize, ppConds);
	}

	case C4FO_Exclude:
		return new C4FindObjectExclude(Data[1].getObj());

	case C4FO_ID:
		return new C4FindObjectDef(Data[1].getPropList());


	// #973: For all criteria using coordinates: If FindObject et al. are called in object context, offset by object center
	case C4FO_InRect:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		int32_t w = Data[3].getInt();
		int32_t h = Data[4].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectInRect(C4Rect(x, y, w, h));
	}

	case C4FO_AtPoint:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectAtPoint(x, y);
	}

	case C4FO_AtRect:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		int32_t w = Data[3].getInt();
		int32_t h = Data[4].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectAtRect(x, y, w, h);
	}

	case C4FO_OnLine:
	{
		int32_t x1 = Data[1].getInt();
		int32_t y1 = Data[2].getInt();
		int32_t x2 = Data[3].getInt();
		int32_t y2 = Data[4].getInt();
		if (context)
		{
			x1 += context->GetX();
			x2 += context->GetX();
			y1 += context->GetY();
			y2 += context->GetY();
		}
		return new C4FindObjectOnLine(x1, y1, x2, y2);
	}

	case C4FO_Distance:
	{
		int32_t x = Data[1].getInt();
		int32_t y = Data[2].getInt();
		if (context)
		{
			x += context->GetX();
			y += context->GetY();
		}
		return new C4FindObjectDistance(x, y, Data[3].getInt());
	}

	case C4FO_OCF:
		return new C4FindObjectOCF(Data[1].getInt());

	case C4FO_Category:
		return new C4FindObjectCategory(Data[1].getInt());

	case C4FO_Action:
	{
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Don't copy, it should be safe
		return new C4FindObjectAction(pStr->GetCStr());
	}

	case C4FO_Func:
	{
		// Get function name
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Construct
		C4FindObjectFunc *pFO = new C4FindObjectFunc(pStr);
		// Add parameters
		for (int i = 2; i < Data.GetSize(); i++)
			pFO->SetPar(i - 2, Data[i]);
		// Done
		return pFO;
	}

	case C4FO_ActionTarget:
	{
		int index = 0;
		if (Data.GetSize() >= 3)
			index = Clamp(Data[2].getInt(), 0, 1);
		return new C4FindObjectActionTarget(Data[1].getObj(), index);
	}

	case C4FO_Procedure:
		return new C4FindObjectProcedure(Data[1].getStr());

	case C4FO_Container:
		return new C4FindObjectContainer(Data[1].getObj());

	case C4FO_AnyContainer:
		return new C4FindObjectAnyContainer();

	case C4FO_Owner:
		return new C4FindObjectOwner(Data[1].getInt());

	case C4FO_Controller:
		return new C4FindObjectController(Data[1].getInt());

	case C4FO_Layer:
		// explicit layer check given. do not add implicit layer check
		if (has_layer_check) *has_layer_check = true;
		return new C4FindObjectLayer(Data[1].getObj());

	case C4FO_InArray:
		return new C4FindObjectInArray(Data[1].getArray());

	case C4FO_Property:
	{
		// Get property name
		C4String *pStr = Data[1].getStr();
		if (!pStr) return NULL;
		// Construct
		C4FindObjectProperty *pFO = new C4FindObjectProperty(pStr);
		// Done
		return pFO;
	}

	case C4FO_AnyLayer:
		// do not add implicit layer check
		if (has_layer_check) *has_layer_check = true;
		return NULL;

	}
	return NULL;
}
示例#17
0
TEST(DirectExecTest, SanityTests)
{
	C4Value rVal(AulExec.DirectExec(nullptr, "5*8", "unit test script", false, nullptr));
	EXPECT_EQ(rVal, C4Value(5*8));
}