示例#1
0
void C4Effect::Kill(C4Object *pObj) {
  // active?
  C4Effect *pLastRemovedEffect = NULL;
  if (IsActive())
    // then temp remove all higher priority effects
    TempRemoveUpperEffects(pObj, 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 (pFnStart && iPriority != 1)
    pFnStart->Exec(pCommandTarget,
                   &C4AulParSet(C4VObj(pObj), C4VInt(iNumber),
                                C4VInt(C4FxCall_TempAddForRemoval)));
  // remove this effect
  int32_t iPrevPrio = iPriority;
  SetDead();
  if (pFnStop)
    if (pFnStop->Exec(pCommandTarget,
                      &C4AulParSet(C4VObj(pObj), C4VInt(iNumber))).getInt() ==
        C4Fx_Stop_Deny)
      // effect denied to be removed: recover
      iPriority = iPrevPrio;
  // reactivate other effects
  TempReaddUpperEffects(pObj, pLastRemovedEffect);
}
示例#2
0
BOOL ObjectComPunch(C4Object *cObj, C4Object *pTarget, int32_t punch)
  {
  if (!cObj || !pTarget) return FALSE;
	if (!punch)
		if (pTarget->GetPhysical()->Fight) 
			punch=BoundBy<int32_t>(5*cObj->GetPhysical()->Fight/pTarget->GetPhysical()->Fight,0,10);
	if (!punch) return TRUE;
	bool fBlowStopped = !!pTarget->Call(PSF_QueryCatchBlow,&C4AulParSet(C4VObj(cObj)));
	if (fBlowStopped && punch>1) punch=punch/2; // half damage for caught blow, so shield+armor help in fistfight and vs monsters
	pTarget->DoEnergy(-punch, false, C4FxCall_EngGetPunched, cObj->Controller);
  int32_t tdir=+1; if (cObj->Action.Dir==DIR_Left) tdir=-1;
  pTarget->Action.ComDir=COMD_Stop;
	// No tumbles when blow was caught
	if (fBlowStopped) return FALSE;
	// Hard punch
	if (punch>=10) 
		if (ObjectActionTumble(pTarget,pTarget->Action.Dir,FIXED100(150)*tdir,itofix(-2)))
			{
			pTarget->LastEnergyLossCausePlayer = cObj->Controller; // for kill tracing when pushing enemies off a cliff
			pTarget->Call(PSF_CatchBlow,&C4AulParSet(C4VInt(punch), C4VObj(cObj)));
			return TRUE;
			}

	// Regular punch
	if (ObjectActionGetPunched(pTarget,FIXED100(250)*tdir,Fix0))
		{
		pTarget->LastEnergyLossCausePlayer = cObj->Controller; // for kill tracing when pushing enemies off a cliff
		pTarget->Call(PSF_CatchBlow,&C4AulParSet(C4VInt(punch), C4VObj(cObj))); 
		return TRUE;
		}

	return FALSE;
  }
示例#3
0
C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs,
                                     const C4LSectors &Sct) {
  // Trivial case
  if (IsImpossible()) return new C4ValueArray();
  C4Rect *pBounds = GetBounds();
  if (!pBounds) return FindMany(Objs);
  // Prepare for array that may be generated
  C4ValueArray *pArray;
  int32_t iSize;
  // Check shape lists?
  if (UseShapes()) {
    // Get area
    C4LArea Area(&Game.Objects.Sectors, *pBounds);
    C4LSector *pSct;
    C4ObjectList *pLst = Area.FirstObjectShapes(&pSct);
    // Check if a single-sector check is enough
    if (!Area.Next(pSct)) return FindMany(pSct->ObjectShapes);
    // Set up array
    pArray = new C4ValueArray(32);
    iSize = 0;
    // Create marker, search all areas
    uint32_t iMarker = ::Game.Objects.GetNextMarker();
    for (; pLst; pLst = Area.NextObjectShapes(pLst, &pSct))
      for (C4ObjectLink *pLnk = pLst->First; pLnk; pLnk = pLnk->Next)
        if (pLnk->Obj->Status)
          if (pLnk->Obj->Marker != iMarker) {
            pLnk->Obj->Marker = iMarker;
            if (Check(pLnk->Obj)) {
              // Grow the array, if neccessary
              if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2);
              // Add object
              (*pArray)[iSize++] = C4VObj(pLnk->Obj);
            }
          }
  } else {
    // Set up array
    pArray = new C4ValueArray(32);
    iSize = 0;
    // Search
    C4LArea Area(&Game.Objects.Sectors, *pBounds);
    C4LSector *pSct;
    for (C4ObjectList *pLst = Area.FirstObjects(&pSct); pLst;
         pLst = Area.NextObjects(pLst, &pSct))
      for (C4ObjectLink *pLnk = pLst->First; pLnk; pLnk = pLnk->Next)
        if (pLnk->Obj->Status)
          if (Check(pLnk->Obj)) {
            // Grow the array, if neccessary
            if (iSize >= pArray->GetSize()) pArray->SetSize(iSize * 2);
            // Add object
            (*pArray)[iSize++] = C4VObj(pLnk->Obj);
          }
  }
  // Shrink array
  pArray->SetSize(iSize);
  // Recheck object status (may shrink array again)
  CheckObjectStatus(pArray);
  // Apply sorting
  if (pSort) pSort->SortObjects(pArray);
  return pArray;
}
示例#4
0
void C4ObjResort::Sort(C4ObjectLink *pFirst, C4ObjectLink *pLast) {
#ifdef _DEBUG
  assert(Game.Objects.Sectors.CheckSort());
#endif
  // do a simple insertion-like sort
  C4ObjectLink *pCurr;      // current link to analyse
  C4ObjectLink *pCurr2;     // second (previous) link to analyse
  C4ObjectLink *pNewFirst;  // next link to be first

  C4ObjectLink *pFirstBck = pFirst;  // backup of first link

  // pre-build parameters
  C4AulParSet Pars;

  // loop until there's nothing left to sort
  while (pFirst != pLast) {
    // start from the very end of the list
    pCurr = pNewFirst = pLast;
    // loop the checks up to the first list item to check
    while (pCurr != pFirst) {
      // get second check item
      pCurr2 = pCurr->Prev;
      while (!pCurr2->Obj->Status) pCurr2 = pCurr2->Prev;
      // perform the check
      Pars[0].Set(C4VObj(pCurr->Obj));
      Pars[1].Set(C4VObj(pCurr2->Obj));
      if (OrderFunc->Exec(NULL, &Pars).getInt() < 0) {
        // so there's something to be reordered: swap the links
        // FIXME: Inform C4ObjectList about this reorder
        C4Object *pObj = pCurr->Obj;
        pCurr->Obj = pCurr2->Obj;
        pCurr2->Obj = pObj;
        // and readd to sector lists
        pCurr->Obj->Unsorted = pCurr2->Obj->Unsorted = TRUE;
        // grow list section to scan next
        pNewFirst = pCurr;
      }
      // advance in list
      pCurr = pCurr2;
    }
    // reduce area to be checked
    pFirst = pNewFirst;
  }
#ifdef _DEBUG
  assert(Game.Objects.Sectors.CheckSort());
#endif
  // resort objects in sector lists
  for (pCurr = pFirstBck; pCurr != pLast->Next; pCurr = pCurr->Next) {
    C4Object *pObj = pCurr->Obj;
    if (pObj->Status && pObj->Unsorted) {
      pObj->Unsorted = FALSE;
      Game.Objects.UpdatePosResort(pObj);
    }
  }
#ifdef _DEBUG
  assert(Game.Objects.Sectors.CheckSort());
#endif
}
示例#5
0
BOOL ObjectComGrab(C4Object *cObj, C4Object *pTarget)
	{
	if (!pTarget) return FALSE;
	if (cObj->GetProcedure()!=DFA_WALK) return FALSE;
	if (!ObjectActionPush(cObj,pTarget)) return FALSE;
	cObj->Call(PSF_Grab, &C4AulParSet(C4VObj(pTarget), C4VBool(true)));
	if (pTarget->Status && cObj->Status)
	{
		pTarget->Controller = cObj->Controller;
		pTarget->Call(PSF_Grabbed, &C4AulParSet(C4VObj(cObj), C4VBool(true)));
	}
	return TRUE;
	}
示例#6
0
void C4Effect::TempRemoveUpperEffects(C4Object *pObj, bool fTempRemoveThis,
                                      C4Effect **ppLastRemovedEffect) {
  if (pObj && !pObj->Status)
    return; // this will be invalid!
  // priority=1: no callbacks
  if (iPriority == 1)
    return;
  // remove from high to low priority
  // recursive implementation...
  C4Effect *pEff = pNext;
  while (pEff)
    if (pEff->IsActive())
      break;
    else
      pEff = pEff->pNext;
  // temp remove active effects with higher priority
  if (pEff)
    pEff->TempRemoveUpperEffects(pObj, true, ppLastRemovedEffect);
  // temp remove this
  if (fTempRemoveThis) {
    FlipActive();
    // temp callbacks only for higher priority effects
    if (pFnStop && iPriority != 1)
      pFnStop->Exec(pCommandTarget,
                    &C4AulParSet(C4VObj(pObj), C4VInt(iNumber),
                                 C4VInt(C4FxCall_Temp), C4VBool(true)));
    if (!*ppLastRemovedEffect)
      *ppLastRemovedEffect = this;
  }
}
示例#7
0
BOOL ObjectComPut(C4Object *cObj, C4Object *pTarget, C4Object *pThing)
  {
  // No object specified, first from contents
	if (!pThing) pThing = cObj->Contents.GetObject();
	// Nothing to put
	if (!pThing) return FALSE;
	// No target
  if (!pTarget) return FALSE;
  // Grabbing: check C4D_Grab_Put
  if (pTarget!=cObj->Contained)
    if (!(pTarget->Def->GrabPutGet & C4D_Grab_Put)) 
      {
      // Was meant to be a drop anyway
      if (ValidPlr(cObj->Owner))
        if (Game.Players.Get(cObj->Owner)->LastComDownDouble)
          return ObjectComDrop(cObj, pThing);
      // No grab put: fail
      return FALSE;
      }
  // Target no fullcon
  if (!(pTarget->OCF & OCF_FullCon)) return FALSE;
	// Check target collection limit
	if (pTarget->Def->CollectionLimit && (pTarget->Contents.ObjectCount()>=pTarget->Def->CollectionLimit)) return FALSE;
  // Transfer thing
	bool fRejectCollect;
  if (!pThing->Enter(pTarget, TRUE, true, &fRejectCollect)) return FALSE;
	// Put call to object script
  cObj->Call(PSF_Put);
	// Target collection call
  pTarget->Call(PSF_Collection,&C4AulParSet(C4VObj(pThing), C4VBool(TRUE)));
	// Success
  return TRUE;
  }
示例#8
0
// return is to be freed by the caller
C4ValueArray *C4FindObject::FindMany(const C4ObjectList &Objs)
{
	// Trivial case
	if (IsImpossible())
		return new C4ValueArray();
	// Set up array
	C4ValueArray *pArray = new C4ValueArray(32);
	int32_t iSize = 0;
	// Search
	for (C4Object *obj : Objs)
		if (obj->Status)
			if (Check(obj))
			{
				// Grow the array, if neccessary
				if (iSize >= pArray->GetSize())
					pArray->SetSize(iSize * 2);
				// Add object
				(*pArray)[iSize++] = C4VObj(obj);
			}
	// Shrink array
	pArray->SetSize(iSize);
	// Recheck object status (may shrink array again)
	CheckObjectStatus(pArray);
	// Apply sorting
	if (pSort) pSort->SortObjects(pArray);
	return pArray;
}
示例#9
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));
}
示例#10
0
BOOL ObjectComUnGrab(C4Object *cObj)
	{
	// Only if pushing, -> stand
	if (cObj->GetProcedure() == DFA_PUSH)
		{
		C4Object *pTarget = cObj->Action.Target;
		if (ObjectActionStand(cObj))
			{
			if (!cObj->CloseMenu(false)) return FALSE;
			cObj->Call(PSF_Grab, &C4AulParSet(C4VObj(pTarget), C4VBool(false)));
			if (pTarget && pTarget->Status && cObj->Status)
				pTarget->Call(PSF_Grabbed, &C4AulParSet(C4VObj(cObj), C4VBool(false)));
			return TRUE;
			}
		}

	return FALSE;
	}
示例#11
0
C4Value C4Effect::DoCall(C4Object *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)
{
	// def script or global only?
	C4PropList *p = GetCallbackScript();
	// compose function name
	char fn[C4AUL_MAX_Identifier+1];
	sprintf(fn, PSF_FxCustom, GetName(), szFn);
	return p->Call(fn, &C4AulParSet(C4VObj(pObj), C4VPropList(this), rVal1, rVal2, rVal3, rVal4, rVal5, rVal6, rVal7));
}
示例#12
0
int32_t C4Object::AddObjectAndContentsToArray(C4ValueArray *target_array, int32_t index)
{
	// add self, contents and child contents count recursively to value array. Return index after last added item.
	target_array->SetItem(index++, C4VObj(this));
	for (C4Object *cobj : Contents)
	{
		index = cobj->AddObjectAndContentsToArray(target_array, index);
	}
	return index;
}
示例#13
0
void ObjectComDigDouble(C4Object *cObj) // "Activation" by DFA_WALK, DFA_DIG, DFA_SWIM
  {  
	C4Object *pTarget;
  DWORD ocf;
  C4PhysicalInfo *phys=cObj->GetPhysical();

	// Contents activation (first contents object only)
	if (cObj->Contents.GetObject())
		if (!! cObj->Contents.GetObject()->Call(PSF_Activate,&C4AulParSet(C4VObj(cObj))))
			return;
  
	// Linekit: Line construction (move to linekit script...)
  if (cObj->Contents.GetObject() && (cObj->Contents.GetObject()->id==C4ID_Linekit)) 
    {
		ObjectComLineConstruction(cObj);
		return;
    }
  
	// Chop
  ocf=OCF_Chop;
  if (phys->CanChop)
		if (cObj->GetProcedure()!=DFA_SWIM)
	    if ((pTarget=Game.Objects.AtObject(cObj->x,cObj->y,ocf,cObj)))
		    if (ocf & OCF_Chop)
			    { 
				  PlayerObjectCommand(cObj->Owner,C4CMD_Chop,pTarget);
					return; 
					}

	// Line construction pick up
  ocf=OCF_LineConstruct;
  if (phys->CanConstruct)
	  if (!cObj->Contents.GetObject())
	    if ((pTarget=Game.Objects.AtObject(cObj->x,cObj->y,ocf,cObj)))
		    if (ocf & OCF_LineConstruct)
			    if (ObjectComLineConstruction(cObj))
						return; 

  // Own activation call
  if (!! cObj->Call(PSF_Activate, &C4AulParSet(C4VObj(cObj)))) return;
	 
  }
示例#14
0
void C4Effect::DoDamage(C4Object *pObj, int32_t &riDamage, int32_t iDamageType, int32_t iCausePlr)
{
	// ask all effects for damage adjustments
	C4Effect *pEff = this;
	do
	{
		if (!pEff->IsDead() && pEff->pFnDamage)
			riDamage = pEff->pFnDamage->Exec(pEff->CommandTarget, &C4AulParSet(C4VObj(pObj), C4VPropList(pEff), C4VInt(riDamage), C4VInt(iDamageType), C4VInt(iCausePlr))).getInt();
		if (pObj && !pObj->Status) return;
	}
	while ((pEff = pEff->pNext) && riDamage);
}
示例#15
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;
}
示例#16
0
void C4Effect::Kill(C4Object *pObj)
{
	// active?
	C4Effect *pLastRemovedEffect=NULL;
	if (IsActive())
		// then temp remove all higher priority effects
		TempRemoveUpperEffects(pObj, 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 (pFnStart && iPriority!=1) pFnStart->Exec(CommandTarget, &C4AulParSet(C4VObj(pObj), C4VPropList(this), C4VInt(C4FxCall_TempAddForRemoval)));
	// remove this effect
	int32_t iPrevPrio = iPriority; SetDead();
	if (pFnStop)
		if (pFnStop->Exec(CommandTarget, &C4AulParSet(C4VObj(pObj), C4VPropList(this), C4VInt(C4FxCall_Normal))).getInt() == C4Fx_Stop_Deny)
			// effect denied to be removed: recover
			iPriority = iPrevPrio;
	// reactivate other effects
	TempReaddUpperEffects(pObj, pLastRemovedEffect);
	// Update OnFire cache
	if (pObj && WildcardMatch(C4Fx_AnyFire, GetName()))
		if (!Get(C4Fx_AnyFire))
			pObj->SetOnFire(false);
}
示例#17
0
void C4Effect::Execute(C4Object *pObj)
{
	// get effect list
	C4Effect **ppEffectList = pObj ? &pObj->pEffects : &Game.pGlobalEffects;
	// execute all effects not marked as dead
	C4Effect *pEffect = this, **ppPrevEffect=ppEffectList;
	do
	{
		// effect dead?
		if (pEffect->IsDead())
		{
			// delete it, then
			C4Effect *pNextEffect = pEffect->pNext;
			pEffect->pNext = NULL;
			delete pEffect;
			// next effect
			*ppPrevEffect = pEffect = pNextEffect;
		}
		else
		{
			// execute effect: time elapsed
			++pEffect->iTime;
			// check timer execution
			if (pEffect->iInterval && !(pEffect->iTime % pEffect->iInterval))
			{
				if (pEffect->pFnTimer)
				{
					if (pEffect->pFnTimer->Exec(pEffect->CommandTarget, &C4AulParSet(C4VObj(pObj), C4VPropList(pEffect), C4VInt(pEffect->iTime))).getInt() == C4Fx_Execute_Kill)
					{
						// safety: this class got deleted!
						if (pObj && !pObj->Status) return;
						// timer function decided to finish it
						pEffect->Kill(pObj);
					}
					// safety: this class got deleted!
					if (pObj && !pObj->Status) return;
				}
				else
					// no timer function: mark dead after time elapsed
					pEffect->Kill(pObj);
			}
			// next effect
			ppPrevEffect = &pEffect->pNext;
			pEffect = pEffect->pNext;
		}
	}
	while (pEffect);
}
示例#18
0
C4Effect * C4Effect::New(C4Object * pForObj, C4String * szName, int32_t iPrio, int32_t iTimerInterval, C4Object * pCmdTarget, C4ID idCmdTarget, const C4Value &rVal1, const C4Value &rVal2, const C4Value &rVal3, const C4Value &rVal4)
{
	C4Effect * pEffect = new C4Effect(pForObj, szName, iPrio, iTimerInterval, pCmdTarget, idCmdTarget, rVal1, rVal2, rVal3, rVal4);
	// ask all effects with higher priority first - except for prio 1 effects, which are considered out of the priority call chain (as per doc)
	bool fRemoveUpper = (iPrio != 1);
	// note that apart from denying the creation of this effect, higher priority effects may also remove themselves
	// or do other things with the effect list
	// (which does not quite make sense, because the effect might be denied by another effect)
	// so the priority is assigned after this call, marking this effect dead before it's definitely valid
	if (fRemoveUpper && pEffect->pNext)
	{
		C4Effect * pEffect2 = pEffect->pNext->Check(pForObj, szName->GetCStr(), iPrio, iTimerInterval, rVal1, rVal2, rVal3, rVal4);
		if (pEffect2)
		{
			// effect denied (iResult = -1), added to an effect (iResult = Number of that effect)
			// or added to an effect that destroyed itself (iResult = -2)
			if (pEffect2 != (C4Effect*)C4Fx_Effect_Deny && pEffect2 != (C4Effect*)C4Fx_Effect_Annul) return pEffect2;
			// effect is still marked dead
			return 0;
		}
	}
	// init effect
	// higher-priority effects must be deactivated temporarily, and then reactivated regarding the new effect
	// higher-level effects should not be inserted during the process of removing or adding a lower-level effect
	// because that would cause a wrong initialization order
	// (hardly ever causing trouble, however...)
	C4Effect *pLastRemovedEffect=NULL;
	if (fRemoveUpper && pEffect->pNext && pEffect->pFnStart)
		pEffect->TempRemoveUpperEffects(pForObj, false, &pLastRemovedEffect);
	// bad things may happen
	if (pForObj && !pForObj->Status) return 0; // this will be invalid!
	pEffect->iPriority = iPrio; // validate effect now
	if (pEffect->pFnStart)
		if (pEffect->pFnStart->Exec(pCmdTarget, &C4AulParSet(C4VObj(pForObj), C4VPropList(pEffect), C4VInt(0), rVal1, rVal2, rVal3, rVal4)).getInt() == C4Fx_Start_Deny)
			// the effect denied to start: assume it hasn't, and mark it dead
			pEffect->SetDead();
	if (fRemoveUpper && pEffect->pNext && pEffect->pFnStart)
		pEffect->TempReaddUpperEffects(pForObj, pLastRemovedEffect);
	if (pForObj && !pForObj->Status) return 0; // this will be invalid!
	// Update OnFire cache
	if (!pEffect->IsDead() && pForObj && WildcardMatch(C4Fx_AnyFire, szName->GetCStr()))
		pForObj->SetOnFire(true);
	return pEffect;
}
示例#19
0
文件: C4Effect.cpp 项目: ev1313/yaC
void C4Effect::TempReaddUpperEffects(C4Object *pObj,
                                     C4Effect *pLastReaddEffect) {
  // nothing to do? - this will also happen if TempRemoveUpperEffects did
  // nothing due to priority==1
  if (!pLastReaddEffect) return;
  if (pObj && !pObj->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->pFnStart && pEff->iPriority != 1)
        pEff->pFnStart->Exec(pEff->pCommandTarget,
                             &C4AulParSet(C4VObj(pObj), C4VInt(pEff->iNumber),
                                          C4VInt(C4FxCall_Temp)));
    }
    // done?
    if (pEff == pLastReaddEffect) break;
  }
}
示例#20
0
文件: C4Effect.cpp 项目: ev1313/yaC
void C4Effect::ClearAll(C4Object *pObj, int32_t iClearFlag) {
  // simply remove access all effects recursively, and do removal calls
  // this does not regard lower-level effects being added in the removal calls,
  // because this could hang the engine with poorly coded effects
  if (pNext) pNext->ClearAll(pObj, iClearFlag);
  if ((pObj && !pObj->Status) || IsDead()) return;
  int32_t iPrevPrio = iPriority;
  SetDead();
  if (pFnStop)
    if (pFnStop->Exec(pCommandTarget,
                      &C4AulParSet(C4VObj(pObj), C4VInt(iNumber),
                                   C4VInt(iClearFlag))).getInt() ==
        C4Fx_Stop_Deny) {
      // this stop-callback might have deleted the object and then denied its
      // own removal
      // must not modify self in this case...
      if (pObj && !pObj->Status) return;
      // effect denied to be removed: recover it
      iPriority = iPrevPrio;
    }
}
示例#21
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:
				if (CommandTarget)
					*pResult = C4VObj(CommandTarget);
				else if (idCommandTarget)
					*pResult = C4VPropList(Definitions.ID2Def(idCommandTarget));
				else
					*pResult = C4VNull;
				//*pResult = CommandTarget ? C4VObj(CommandTarget) :
				//           (idCommandTarget ? C4VPropList(Definitions.ID2Def(idCommandTarget)) : C4VNull);
				return true;
			case P_Time: *pResult = C4VInt(iTime); return true;
		}
	}
	return C4PropListNumbered::GetPropertyByS(k, pResult);
}
示例#22
0
C4Effect::C4Effect(C4Object *pForObj, const char *szName, int32_t iPrio,
                   int32_t iTimerIntervall, C4Object *pCmdTarget,
                   C4ID idCmdTarget, C4Value &rVal1, C4Value &rVal2,
                   C4Value &rVal3, C4Value &rVal4, bool fDoCalls,
                   int32_t &riStoredAsNumber)
    : EffectVars(0) {
  C4Effect *pPrev, *pCheck;
  // assign values
  SCopy(szName, Name, C4MaxDefString);
  iPriority = 0; // effect is not yet valid; some callbacks to other effects are
                 // done before
  riStoredAsNumber = 0;
  iIntervall = iTimerIntervall;
  iTime = 0;
  pCommandTarget = pCmdTarget;
  idCommandTarget = idCmdTarget;
  AssignCallbackFunctions();
  // get effect target
  C4Effect **ppEffectList = pForObj ? &pForObj->pEffects : &Game.pGlobalEffects;
  // assign a unique number for that object
  iNumber = 1;
  for (pCheck = *ppEffectList; pCheck; pCheck = pCheck->pNext)
    if (pCheck->iNumber >= iNumber)
      iNumber = pCheck->iNumber + 1;
  // register into object
  pPrev = *ppEffectList;
  if (pPrev && Abs(pPrev->iPriority) < iPrio) {
    while (pCheck = pPrev->pNext)
      if (Abs(pCheck->iPriority) >= iPrio)
        break;
      else
        pPrev = pCheck;
    // insert after previous
    pNext = pPrev->pNext;
    pPrev->pNext = this;
  } else {
    // insert as first effect
    pNext = *ppEffectList;
    *ppEffectList = this;
  }
  // no calls to be done: finished here
  if (!fDoCalls)
    return;
  // ask all effects with higher priority first - except for prio 1 effects,
  // which are considered out of the priority call chain (as per doc)
  bool fRemoveUpper = (iPrio != 1);
  // note that apart from denying the creation of this effect, higher priority
  // effects may also remove themselves
  // or do other things with the effect list
  // (which does not quite make sense, because the effect might be denied by
  // another effect)
  // so the priority is assigned after this call, marking this effect dead
  // before it's definitely valid
  if (fRemoveUpper && pNext) {
    int32_t iResult = pNext->Check(pForObj, Name, iPrio, iIntervall, rVal1,
                                   rVal2, rVal3, rVal4);
    if (iResult) {
      // effect denied (iResult = -1), added to an effect (iResult = Number of
      // that effect)
      // or added to an effect that destroyed itself (iResult = -2)
      if (iResult != C4Fx_Effect_Deny)
        riStoredAsNumber = iResult;
      // effect is still marked dead
      return;
    }
  }
  // init effect
  // higher-priority effects must be deactivated temporarily, and then
  // reactivated regarding the new effect
  // higher-level effects should not be inserted during the process of removing
  // or adding a lower-level effect
  // because that would cause a wrong initialization order
  // (hardly ever causing trouble, however...)
  C4Effect *pLastRemovedEffect = NULL;
  if (fRemoveUpper && pNext && pFnStart)
    TempRemoveUpperEffects(pForObj, false, &pLastRemovedEffect);
  // bad things may happen
  if (pForObj && !pForObj->Status)
    return;          // this will be invalid!
  iPriority = iPrio; // validate effect now
  if (pFnStart)
    if (pFnStart->Exec(pCommandTarget,
                       &C4AulParSet(C4VObj(pForObj), C4VInt(iNumber), C4VInt(0),
                                    rVal1, rVal2, rVal3, rVal4)).getInt() ==
        C4Fx_Start_Deny)
      // the effect denied to start: assume it hasn't, and mark it dead
      SetDead();
  if (fRemoveUpper && pNext && pFnStart)
    TempReaddUpperEffects(pForObj, pLastRemovedEffect);
  if (pForObj && !pForObj->Status)
    return; // this will be invalid!
  // this effect has been created; hand back the number
  riStoredAsNumber = iNumber;
}
示例#23
0
void C4GameObjects::CrossCheck()  // Every Tick1 by ExecObjects
{
  C4Object *obj1 = nullptr, *obj2 = nullptr;
  DWORD ocf1, ocf2, focf, tocf;

  // AtObject-Check: Checks for first match of obj1 at obj2

  // Checks for this frame
  focf = tocf = OCF_None;
  // Medium level: Fight
  if (!Tick5) {
    focf |= OCF_FightReady;
    tocf |= OCF_FightReady;
  }
  // Very low level: Incineration
  if (!Tick35) {
    focf |= OCF_OnFire;
    tocf |= OCF_Inflammable;
  }

  if (focf && tocf)
    for (C4ObjectList::iterator iter = begin(); iter != end() && (obj1 = *iter);
         ++iter)
      if (obj1->Status && !obj1->Contained)
        if (obj1->OCF & focf) {
          ocf1 = obj1->OCF;
          ocf2 = tocf;
          if (obj2 = AtObject(obj1->x, obj1->y, ocf2, obj1)) {
            // Incineration
            if ((ocf1 & OCF_OnFire) && (ocf2 & OCF_Inflammable))
              if (!Random(obj2->Def->ContactIncinerate)) {
                obj2->Incinerate(obj1->GetFireCausePlr(), FALSE, obj1);
                continue;
              }
            // Fight
            if ((ocf1 & OCF_FightReady) && (ocf2 & OCF_FightReady))
              if (Game.Players.Hostile(obj1->Owner, obj2->Owner)) {
                // RejectFight callback
                C4AulParSet parset1(C4VObj(obj2));
                C4AulParSet parset2(C4VObj(obj1));
                if (obj1->Call(PSF_RejectFight, &parset1).getBool()) continue;
                if (obj2->Call(PSF_RejectFight, &parset2).getBool()) continue;
                ObjectActionFight(obj1, obj2);
                ObjectActionFight(obj2, obj1);
                continue;
              }
          }
        }

  // Reverse area check: Checks for all obj2 at obj1

  focf = tocf = OCF_None;
  // High level: Collection, Hit
  if (!Tick3) {
    focf |= OCF_Collection;
    tocf |= OCF_Carryable;
  }
  focf |= OCF_Alive;
  tocf |= OCF_HitSpeed2;

  if (focf && tocf)
    for (C4ObjectList::iterator iter = begin(); iter != end() && (obj1 = *iter);
         ++iter)
      if (obj1->Status && !obj1->Contained && (obj1->OCF & focf)) {
        uint32_t Marker = GetNextMarker();
        C4LSector *pSct;
        for (C4ObjectList *pLst = obj1->Area.FirstObjects(&pSct); pLst;
             pLst = obj1->Area.NextObjects(pLst, &pSct))
          for (C4ObjectList::iterator iter2 = pLst->begin();
               iter2 != pLst->end() && (obj2 = *iter2); ++iter2)
            if (obj2->Status && !obj2->Contained && (obj2 != obj1) &&
                (obj2->OCF & tocf))
              if (Inside<int32_t>(obj2->x - (obj1->x + obj1->Shape.x), 0,
                                  obj1->Shape.Wdt - 1))
                if (Inside<int32_t>(obj2->y - (obj1->y + obj1->Shape.y), 0,
                                    obj1->Shape.Hgt - 1))
                  if (obj1->pLayer == obj2->pLayer) {
                    // handle collision only once
                    if (obj2->Marker == Marker) continue;
                    obj2->Marker = Marker;
                    // Hit
                    if ((obj2->OCF & OCF_HitSpeed2) &&
                        (obj1->OCF & OCF_Alive) &&
                        (obj2->Category & C4D_Object))
                      if (!obj1->Call(PSF_QueryCatchBlow,
                                      &C4AulParSet(C4VObj(obj2)))) {
                        if (true /* "realistic" hit energy */) {
                          FIXED dXDir = obj2->xdir - obj1->xdir,
                                dYDir = obj2->ydir - obj1->ydir;
                          int32_t iHitEnergy = fixtoi(
                              (dXDir * dXDir + dYDir * dYDir) * obj2->Mass / 5);
                          iHitEnergy = Max<int32_t>(
                              iHitEnergy / 3,
                              !!iHitEnergy);  // hit energy reduced to 1/3rd,
                                              // but do not drop to zero because
                                              // of this division
                          obj1->DoEnergy(-iHitEnergy / 5, false,
                                         C4FxCall_EngObjHit, obj2->Controller);
                          int tmass = Max<int32_t>(obj1->Mass, 50);
                          if (!Tick3 ||
                              (obj1->Action.Act >= 0 &&
                               obj1->Def->ActMap[obj1->Action.Act].Procedure !=
                                   DFA_FLIGHT))
                            obj1->Fling(obj2->xdir * 50 / tmass,
                                        -Abs(obj2->ydir / 2) * 50 / tmass,
                                        false, obj2->Controller);
                          obj1->Call(PSF_CatchBlow,
                                     &C4AulParSet(C4VInt(-iHitEnergy / 5),
                                                  C4VObj(obj2)));
                        } else {
                          obj1->DoEnergy(-obj2->Mass / 5, false,
                                         C4FxCall_EngObjHit, obj2->Controller);
                          int tmass = Max<int32_t>(obj1->Mass, 50);
                          obj1->Fling(obj2->xdir * 50 / tmass,
                                      -Abs(obj2->ydir / 2) * 50 / tmass, false,
                                      obj2->Controller);
                          obj1->Call(PSF_CatchBlow,
                                     &C4AulParSet(C4VInt(-obj2->Mass / 5),
                                                  C4VObj(obj2)));
                        }
                        // obj1 might have been tampered with
                        if (!obj1->Status || obj1->Contained ||
                            !(obj1->OCF & focf))
                          goto out1;
                        continue;
                      }
                    // Collection
                    if ((obj1->OCF & OCF_Collection) &&
                        (obj2->OCF & OCF_Carryable))
                      if (Inside<int32_t>(
                              obj2->x - (obj1->x + obj1->Def->Collection.x), 0,
                              obj1->Def->Collection.Wdt - 1))
                        if (Inside<int32_t>(
                                obj2->y - (obj1->y + obj1->Def->Collection.y),
                                0, obj1->Def->Collection.Hgt - 1)) {
                          // if(!pLst->First) BREAKPOINT_HERE;
                          obj1->Collect(obj2);
                          // if(!pLst->First)  BREAKPOINT_HERE;
                          // obj1 might have been tampered with
                          if (!obj1->Status || obj1->Contained ||
                              !(obj1->OCF & focf))
                            goto out1;
                        }
                  }
      out1:
        ;
      }

  // Contained-Check: Checks for matching Contained

  // Checks for this frame
  focf = tocf = OCF_None;
  // Low level: Fight
  if (!Tick10) {
    focf |= OCF_FightReady;
    tocf |= OCF_FightReady;
  }

  if (focf && tocf)
    for (C4ObjectList::iterator iter = begin(); iter != end() && (obj1 = *iter);
         ++iter)
      if (obj1->Status && obj1->Contained && (obj1->OCF & focf)) {
        for (C4ObjectList::iterator iter2 = obj1->Contained->Contents.begin();
             iter2 != end() && (obj2 = *iter2); ++iter2)
          if (obj2->Status && obj2->Contained && (obj2 != obj1) &&
              (obj2->OCF & tocf))
            if (obj1->pLayer == obj2->pLayer) {
              ocf1 = obj1->OCF;
              ocf2 = obj2->OCF;
              // Fight
              if ((ocf1 & OCF_FightReady) && (ocf2 & OCF_FightReady))
                if (Game.Players.Hostile(obj1->Owner, obj2->Owner)) {
                  ObjectActionFight(obj1, obj2);
                  ObjectActionFight(obj2, obj1);
                  // obj1 might have been tampered with
                  if (!obj1->Status || obj1->Contained || !(obj1->OCF & focf))
                    goto out2;
                  continue;
                }
            }
      out2:
        ;
      }
}
示例#24
0
void C4ObjResort::SortObject() {
  // safety
  if (pSortObj->Status != C4OS_NORMAL || pSortObj->Unsorted) return;
  // pre-build parameters
  C4AulParSet Pars;
  Pars[1].Set(C4VObj(pSortObj));
  // first, check forward in list
  C4ObjectLink *pMoveLink = NULL;
  C4ObjectLink *pLnk = Game.Objects.GetLink(pSortObj);
  C4ObjectLink *pLnkBck = pLnk;
  C4Object *pObj2;
  int iResult;
  if (!pLnk) return;
  while (pLnk = pLnk->Next) {
    // get object
    pObj2 = pLnk->Obj;
    if (!pObj2->Status) continue;
    // does the category still match?
    if (!(pObj2->Category & pSortObj->Category)) break;
    // perform the check
    Pars[0].Set(C4VObj(pObj2));
    iResult = OrderFunc->Exec(NULL, &Pars).getInt();
    if (iResult > 0) break;
    if (iResult < 0) pMoveLink = pLnk;
  }
  // check if movement has to be done
  if (pMoveLink) {
    // move link directly after pMoveLink
    // FIXME: Inform C4ObjectList that this is a reorder, not a remove+insert
    // move out of current position
    Game.Objects.RemoveLink(pLnkBck);
    // put into new position
    Game.Objects.InsertLink(pLnkBck, pMoveLink);
  } else {
    // no movement yet: check backwards in list
    Pars[0].Set(C4VObj(pSortObj));
    pLnk = pLnkBck;
    while (pLnk = pLnk->Prev) {
      // get object
      pObj2 = pLnk->Obj;
      if (!pObj2->Status) continue;
      // does the category still match?
      if (!(pObj2->Category & pSortObj->Category)) break;
      // perform the check
      Pars[1].Set(C4VObj(pObj2));
      iResult = OrderFunc->Exec(NULL, &Pars).getInt();
      if (iResult > 0) break;
      if (iResult < 0) pMoveLink = pLnk;
    }
    // no movement to be done? finish
    if (!pMoveLink) return;
    // move link directly before pMoveLink
    // move out of current position
    Game.Objects.RemoveLink(pLnkBck);
    // put into new position
    Game.Objects.InsertLinkBefore(pLnkBck, pMoveLink);
  }
  // object has been resorted: resort into area lists, too
  Game.Objects.UpdatePosResort(pSortObj);
  // done
}