Пример #1
0
void C4Object::GrabContents(C4Object *pFrom)
{
	// create a temp list of all objects and transfer it
	// this prevents nasty deadlocks caused by RejectEntrance-scripts
	C4ObjectList tmpList; tmpList.Copy(pFrom->Contents);
	for (C4Object *obj : tmpList)
		if (obj->Status)
			obj->Enter(this);
}
Пример #2
0
int32_t C4FindObject::Count(const C4ObjectList &Objs) {
  // Trivial cases
  if (IsImpossible()) return 0;
  if (IsEnsured()) return Objs.ObjectCount();
  // Count
  int32_t iCount = 0;
  for (C4ObjectLink *pLnk = Objs.First; pLnk; pLnk = pLnk->Next)
    if (pLnk->Obj->Status)
      if (Check(pLnk->Obj)) iCount++;
  return iCount;
}
Пример #3
0
int32_t C4FindObject::Count(const C4ObjectList &Objs)
{
	// Trivial cases
	if (IsImpossible())
		return 0;
	if (IsEnsured())
		return Objs.ObjectCount();
	// Count
	int32_t iCount = 0;
	for (C4Object *obj : Objs)
		if (obj->Status && Check(obj))
			iCount++;
	return iCount;
}
Пример #4
0
int32_t C4FindObject::Count(const C4ObjectList &Objs, const C4LSectors &Sct)
{
	// Trivial cases
	if (IsImpossible())
		return 0;
	if (IsEnsured())
		return Objs.ObjectCount();
	// Check bounds
	C4Rect *pBounds = GetBounds();
	if (!pBounds)
		return Count(Objs);
	else if (UseShapes())
	{
		// Get area
		C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct;
		C4ObjectList *pLst = Area.FirstObjectShapes(&pSct);
		// Check if a single-sector check is enough
		if (!Area.Next(pSct))
			return Count(pSct->ObjectShapes);
		// Create marker, count over all areas
		uint32_t iMarker = ::Objects.GetNextMarker();
		int32_t iCount = 0;
		for (; pLst; pLst=Area.NextObjectShapes(pLst, &pSct))
			for (C4Object *obj : Objs)
				if (obj->Status)
					if (obj->Marker != iMarker)
					{
						obj->Marker = iMarker;
						if (Check(obj))
							iCount++;
					}
		return iCount;
	}
	else
	{
		// Count objects per area
		C4LArea Area(&::Objects.Sectors, *pBounds); C4LSector *pSct;
		int32_t iCount = 0;
		for (C4ObjectList *pLst=Area.FirstObjects(&pSct); pLst; pLst=Area.NextObjects(pLst, &pSct))
			iCount += Count(*pLst);
		return iCount;
	}
}
Пример #5
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:
        ;
      }
}
Пример #6
0
C4ObjectList::iterator::iterator(const C4ObjectList & List, const C4ObjectLink * pLink, bool reverse):
		List(List), link(pLink ? *pLink : NULL_LINK), reverse(reverse)
{
	Next=List.AddIter(this);
}