Esempio n. 1
0
            void PopulateOctree(const WorldPoint& p0, const WorldPoint& p1, const Iter& begin, const Iter& end, bool canKeepAll = false)
            {
                m_p0 = p0;
                m_p1 = p1;

                // Only include those elements that have a portion in this tree.
                for(Iter iter = begin; iter != end; ++iter)
                {
                    WorldPoint min = (*iter)->GetMinExtent();
                    WorldPoint max = (*iter)->GetMaxExtent();


                    if( BoxesIntersect(min, max, m_p0, m_p1) )
                    {
                        m_objects.push_back(*iter);
                    }
                }

                // If any child has the same number of objects as this level, then 
                // we'll hit an infinite loop.
                if( !canKeepAll && this->GetNumObjects() == std::distance(begin, end) )
                {
                    return;
                }

                if( m_objects.size() > m_minObjects )
                {
                    PopulateSubTrees();
                }
            }
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pObject - 
//-----------------------------------------------------------------------------
void CCullTreeNode::AddCullTreeObjectRecurse(CMapClass *pObject)
{
	//
	// If the object intersects this node, add it to this node and recurse,
	// testing each of our children in the same fashion.
	//
	Vector ObjMins;
	Vector ObjMaxs;
	pObject->GetCullBox(ObjMins, ObjMaxs);
	if (BoxesIntersect(ObjMins, ObjMaxs, bmins, bmaxs))
	{
		int nChildCount = GetChildCount();
		if (nChildCount != 0)
		{
			// dvs: we should split when appropriate!
			// otherwise the tree becomes less optimal over time.
			for (int nChild = 0; nChild < nChildCount; nChild++)
			{
				CCullTreeNode *pChild = GetCullTreeChild(nChild);
				pChild->AddCullTreeObjectRecurse(pObject);
			}
		}
		else
		{
			AddCullTreeObject(pObject);
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pObject - The object whose bounding box has changed.
//-----------------------------------------------------------------------------
void CCullTreeNode::UpdateAllCullTreeObjectsRecurse(void)
{
	int nChildCount = GetChildCount();
	if (nChildCount != 0)
	{
		for (int nChild = 0; nChild < nChildCount; nChild++)
		{
			CCullTreeNode *pChild = GetCullTreeChild(nChild);
			pChild->UpdateAllCullTreeObjectsRecurse();
		}
	}
	else
	{
		int nObjectCount = GetObjectCount();
		for (int nObject = 0; nObject < nObjectCount; nObject++)
		{
			CMapClass *pObject = GetCullTreeObject(nObject);

			Vector mins;
			Vector maxs;
			pObject->GetCullBox(mins, maxs);
			if (!BoxesIntersect(mins, maxs, bmins, bmaxs))
			{
				RemoveCullTreeObject(pObject);
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pObject - 
//-----------------------------------------------------------------------------
void CCullTreeNode::UpdateCullTreeObject(CMapClass *pObject)
{
	Vector mins;
	Vector maxs;
	pObject->GetCullBox(mins, maxs);

	if (!BoxesIntersect(mins, maxs, bmins, bmaxs))
	{
		RemoveCullTreeObject(pObject);
	}
	else
	{
		AddCullTreeObject(pObject);
	}
}
Esempio n. 5
0
void CMapWorld::CullTree_SplitNode(CCullTreeNode *pNode)
{
	Vector Mins;
	Vector Maxs;
	Vector Size;

	pNode->GetBounds(Mins, Maxs);
	VectorSubtract(Maxs, Mins, Size);

	if ((Size[0] > MIN_NODE_DIM) && (Size[1] > MIN_NODE_DIM) && (Size[2] > MIN_NODE_DIM))
	{
		Vector Mids;
		int nChild;

		Mids[0] = (Mins[0] + Maxs[0]) / 2.0;
		Mids[1] = (Mins[1] + Maxs[1]) / 2.0;
		Mids[2] = (Mins[2] + Maxs[2]) / 2.0;

		for (nChild = 0; nChild < 8; nChild++)
		{
			Vector ChildMins;
			Vector ChildMaxs;

			//
			// Create a child and set its bounding box.
			//
			CCullTreeNode *pChild = new CCullTreeNode;

			if (nChild & 1)
			{
				ChildMins[0] = Mins[0];
				ChildMaxs[0] = Mids[0];
			}
			else
			{
				ChildMins[0] = Mids[0];
				ChildMaxs[0] = Maxs[0];
			}

			if (nChild & 2)
			{
				ChildMins[1] = Mins[1];
				ChildMaxs[1] = Mids[1];
			}
			else
			{
				ChildMins[1] = Mids[1];
				ChildMaxs[1] = Maxs[1];
			}

			if (nChild & 4)
			{
				ChildMins[2] = Mins[2];
				ChildMaxs[2] = Mids[2];
			}
			else
			{
				ChildMins[2] = Mids[2];
				ChildMaxs[2] = Maxs[2];
			}

			pChild->UpdateBounds(ChildMins, ChildMaxs);
			
			pNode->AddCullTreeChild(pChild);

			Vector mins1;
			Vector maxs1;
			pChild->GetBounds(mins1, maxs1);

			//
			// Check all objects in this node against the child's bounding box, adding the
			// objects that intersect to the child's object list.
			//
			int nObjectCount = pNode->GetObjectCount();
			for (int nObject = 0; nObject < nObjectCount; nObject++)
			{
				CMapClass *pObject = pNode->GetCullTreeObject(nObject);
				Assert(pObject != NULL);

				Vector mins2;
				Vector maxs2;
				pObject->GetCullBox(mins2, maxs2);
				if (BoxesIntersect(mins1, maxs1, mins2, maxs2))
				{
					pChild->AddCullTreeObject(pObject);
				}
			}
		}
				
		//
		// Remove all objects from this node's object list (since we are not a leaf).
		//
		pNode->RemoveAllCullTreeObjects();

		//
		// Recurse into all children with at least two objects, splitting them.
		//
		int nChildCount = pNode->GetChildCount();
		for (nChild = 0; nChild < nChildCount; nChild++)
		{
			CCullTreeNode *pChild = pNode->GetCullTreeChild(nChild);
			if (pChild->GetObjectCount() >= MIN_NODE_OBJECT_SPLIT)
			{
				CullTree_SplitNode(pChild);
			}
		}
	}
}
Esempio n. 6
0
int main(int argc, char* argv[])
{
  const int NUM_OBJECTS = 40; // Number of objects in test set, must be > FRAC_OBJECTS for this test
  const int FRAC_OBJECTS = 4;
  const float MAX_WORLDSIZE = 10.0f;
  const float FRAC_WORLDSIZE = MAX_WORLDSIZE / 2;

  // typedef the RTree useage just for conveniance with iteration
  typedef RTree<SomeThing*, float, 3> SomeThingTree;

  ASSERT( NUM_OBJECTS > FRAC_OBJECTS );

  int index; // general purpose counter, declared here because MSVC 6 is not ansi compliant with 'for' loops.
  SomeThing* thingArray[NUM_OBJECTS * 2]; // Store objects in another container to test with, sized larger than we need

  memset(thingArray, 0, sizeof(thingArray)); // Nullify array, size is known here


  // Create intance of RTree

  SomeThingTree tree; 

  
  // Add some nodes
  int counter = 0;
  for( index = 0; index < NUM_OBJECTS; ++index )
  {
    SomeThing* newThing = new SomeThing;

    newThing->m_creationCounter = counter++;
    newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
    Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
    newThing->m_max = newThing->m_min + extent;

    thingArray[counter-1] = newThing;

    tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
    printf("inserting %d\n", newThing->m_creationCounter);
  }

  printf("tree count = %d\n", tree.Count());

  int numToDelete = NUM_OBJECTS / FRAC_OBJECTS;
  int numToStep = FRAC_OBJECTS;

  // Delete some nodes
  for( index = 0; index < NUM_OBJECTS; index += numToStep )
  {
    SomeThing* curThing = thingArray[index];

    if(curThing)
    {
      tree.Remove(curThing->m_min.v, curThing->m_max.v, curThing);
      printf("removing %d\n", curThing->m_creationCounter);

      delete curThing;
      thingArray[index] = NULL;
    }
  }

  printf("tree count = %d\n", tree.Count());

  // Add some more nodes
  for( index = 0; index < numToDelete; ++index )
  {
    SomeThing* newThing = new SomeThing;

    newThing->m_creationCounter = counter++;
    newThing->m_min = Vec3(RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE), RandFloat(-MAX_WORLDSIZE, MAX_WORLDSIZE));
    Vec3 extent = Vec3(RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE), RandFloat(0, FRAC_WORLDSIZE));
    newThing->m_max = newThing->m_min + extent;
    
    thingArray[counter-1] = newThing;

    tree.Insert(newThing->m_min.v, newThing->m_max.v, newThing);
    printf("inserting %d\n", newThing->m_creationCounter);
  }

  printf("tree count = %d\n", tree.Count());

  Vec3 searchMin(0,0,0);
  Vec3 searchMax(FRAC_WORLDSIZE, FRAC_WORLDSIZE, FRAC_WORLDSIZE); 
  tree.Search(searchMin.v, searchMax.v, &QueryResultCallback, NULL);

  // NOTE: Even better than just dumping text, it would be nice to render the 
  // tree contents and search result for visualization.
 

  // List values.  Iterator is NOT delete safe
  SomeThingTree::Iterator it;
  for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
  {
    SomeThing* curThing = tree.GetAt(it);

    if(BoxesIntersect(searchMin, searchMax, curThing->m_min, curThing->m_max))
    {
      printf("brute found %d\n", curThing->m_creationCounter);
    }
  }

  // Delete our nodes, NOTE, we are NOT deleting the tree nodes, just our data
  // of course the tree will now contain invalid pointers that must not be used any more.
  for( tree.GetFirst(it); !tree.IsNull(it); tree.GetNext(it) )
  {
    SomeThing* removeElem = tree.GetAt(it);
    if(removeElem)
    {
      printf("deleting %d\n", removeElem->m_creationCounter);
      delete removeElem;
    }
  }

  // Remove all contents (This would have happened automatically during destructor)
  tree.RemoveAll();
 
  if(SomeThing::s_outstandingAllocs > 0)
  {
    printf("Memory leak!\n");
    printf("s_outstandingAllocs = %d\n", SomeThing::s_outstandingAllocs);
  }
  else
  {
    printf("No memory leaks detected by app\n");
  }

  // Wait for keypress on exit so we can read console output
  getchar(); 

#ifdef WIN32
  // Use CRT Debug facility to dump memory leaks on app exit
  SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF );
#endif //WIN32

  return 0;
}
Esempio n. 7
0
void CTriggerFX::CheckPlayersWithinTrigger()
{
	if( m_cs.bLocked )
		return;

	// Get a list of all the characters...

	CSpecialFXList *pList = g_pGameClientShell->GetSFXMgr()->GetFXList( SFX_CHARACTER_ID );
	if( !pList )
		return;

	int nListSize = pList->GetSize();
	int nNumChars = pList->GetNumItems();
	int nNumFoundChars = 0;
	int nNumPlayersFound = 0;
	uint32 dwLocalId = 0;

	g_pLTClient->GetLocalClientID( &dwLocalId );

	LTVector vTrigPos, vPlayerPos, vPlayerDims, vPlayerMin, vPlayerMax;
	g_pLTClient->GetObjectPos( m_hServerObject, &vTrigPos );

	// Setup the triggers box...
	
	LTVector vTrigMin = vTrigPos - m_cs.vDims;
	LTVector vTrigMax = vTrigPos + m_cs.vDims;

	bool bLocalPlayerIn = false;
	
	// Initialize our containers to zero.  Don't call clear, since we'll be using
	// these vectors every frame and most likely they will have the same
	// number of elements across multiple frames.
	m_lstPlayersNotInTrigger.resize( 0 );
	m_lstNewPlayersInTrigger.resize( 0 );

	for( int i = 0; i < nListSize; ++i )
	{
		// Try not to go through the entire list...

		if( nNumFoundChars == nNumChars )
			break;

		if( (*pList)[i] )
		{
			CCharacterFX *pChar = (CCharacterFX*)(*pList)[i];
			if( !pChar )
				continue;

			// Found another char..
			++nNumFoundChars;

			if( pChar->m_cs.bIsPlayer && pChar->m_cs.nClientID != ( uint8 )-1 )
			{
				++nNumPlayersFound;
				
				HOBJECT hPlayer = pChar->GetServerObj();

				g_pLTClient->GetObjectPos( hPlayer, &vPlayerPos );
				g_pPhysicsLT->GetObjectDims( hPlayer, &vPlayerDims );

				vPlayerMin = vPlayerPos - vPlayerDims;
				vPlayerMax = vPlayerPos + vPlayerDims;

				// Check the current list of players in the trigger for this player...
					
				CharFXList::iterator iter;
				for( iter = m_lstCurPlayersInTrigger.begin(); iter != m_lstCurPlayersInTrigger.end(); ++iter )
				{
					if( pChar == (*iter) )
						break;
				}

				// Check if we are within the height of the trigger...

				bool bWithinHeight = false;
				if( vPlayerMax.y > vTrigMin.y && vPlayerMin.y < vTrigMax.y )
					bWithinHeight = true;

				if( bWithinHeight && BoxesIntersect( vTrigMin, vTrigMax, vPlayerMin, vPlayerMax ) && !pChar->IsPlayerDead())
				{
					if( dwLocalId == pChar->m_cs.nClientID )
						bLocalPlayerIn = true;

					// If it wasn't in the list add it...

					if( iter == m_lstCurPlayersInTrigger.end() )
					{
						m_lstCurPlayersInTrigger.push_back( pChar );
						m_lstNewPlayersInTrigger.push_back( pChar );
					}

				}
				else
				{
					if( iter != m_lstCurPlayersInTrigger.end() )
						m_lstCurPlayersInTrigger.erase( iter );

					m_lstPlayersNotInTrigger.push_back( pChar );
				}
			}
		}
	}

	wchar_t wszBuffer[256];

	if( (m_lstNewPlayersInTrigger.size() > 0) && (nNumPlayersFound > 1) )
	{
		CClientInfoMgr *pInfoMgr = g_pInterfaceMgr->GetClientInfoMgr();
		if( !pInfoMgr )
			return;

		if( bLocalPlayerIn )
		{
			// Display a general transmission and messages for each player you are waiting for...

			int nPlayersNotInTrig = m_lstPlayersNotInTrigger.size();

			if( m_cs.nPlayerInsideID != (uint32)-1 )
			{
				g_pTransmission->Show( StringIDFromIndex(m_cs.nPlayerInsideID) );
			}
			else if( nPlayersNotInTrig > 1 )
			{
				//sTransmission.Format( "You are waiting for %i players.", nPlayersNotInTrig );
				FormatString( "IDS_EXIT_PLAYER_WAITING", wszBuffer, LTARRAYSIZE(wszBuffer), nPlayersNotInTrig );
				g_pTransmission->Show( wszBuffer );
			}
			else
			{
				//sTransmission.Format( "You are waiting for 1 player." );
				FormatString( "IDS_EXIT_PLAYER_WAITING_1", wszBuffer, LTARRAYSIZE(wszBuffer) );
				g_pTransmission->Show( wszBuffer );
			}		
			
			
			CharFXList::iterator iter;
			for( iter = m_lstPlayersNotInTrigger.begin(); iter != m_lstPlayersNotInTrigger.end(); ++iter )
			{
				//sMessage.Format( "You are waiting for %s.", pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID ));
				FormatString( "IDS_EXIT_PLAYER_WAITING_NAME", wszBuffer, LTARRAYSIZE(wszBuffer), pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID) );
				g_pGameMsgs->AddMessage( wszBuffer );
			}
		}
		else
		{
			// Display a general transmission and messages for each player waiting for you...

			int nPlayersInTrig = m_lstCurPlayersInTrigger.size();
			
			if( m_cs.nPlayerOutsideID != (uint32)-1 )
			{
				g_pTransmission->Show( LoadString(m_cs.nPlayerOutsideID) );
			}
			else if( nPlayersInTrig > 1 )
			{
//				sTransmission.Format( "%i players are waiting for you",nPlayersInTrig  );
				FormatString( "IDS_EXIT_WAITING", wszBuffer, LTARRAYSIZE(wszBuffer), nPlayersInTrig );
				g_pTransmission->Show( wszBuffer );
			}
			else
			{
//				sTransmission.Format( "1 player is waiting for you." );
				FormatString( "IDS_EXIT_WAITING_1", wszBuffer, LTARRAYSIZE(wszBuffer) );
				g_pTransmission->Show( wszBuffer );
			}
			

			CharFXList::iterator iter;
			for( iter = m_lstCurPlayersInTrigger.begin(); iter != m_lstCurPlayersInTrigger.end(); ++iter )
			{
				FormatString( "IDS_EXIT_WAITING_NAME", wszBuffer, LTARRAYSIZE(wszBuffer), pInfoMgr->GetPlayerName( (*iter)->m_cs.nClientID) );
				g_pGameMsgs->AddMessage( wszBuffer );	
			}
		}
	}
}
Esempio n. 8
0
void CTriggerFX::CalcLocalClientDistance()
{
	m_fDistPercent = -1.0f;

	// Don't do anything if the trigger is locked or our distances are too small..

	if( m_cs.bLocked || (m_cs.fHUDAlwaysOnDist <= 0.0f && m_cs.fHUDLookAtDist <= 0.0f) )
		return;

	// See if the player is within the trigger...

	LTVector vTrigPos;
	g_pLTClient->GetObjectPos( m_hServerObject, &vTrigPos );
	g_pLTClient->SetObjectPos( m_hDimsObject, vTrigPos );

	HLOCALOBJ	hPlayerObj = g_pLTClient->GetClientObject();
	LTVector	vPlayerPos, vPlayerDims;

	g_pLTClient->GetObjectPos( hPlayerObj, &vPlayerPos );

	// Make sure we are within the display radius...
	
	float	fMaxRadius = LTMAX( m_cs.fHUDAlwaysOnDist, m_cs.fHUDLookAtDist );
	float	fDistSqr = vTrigPos.DistSqr( vPlayerPos );
	bool	bWithinLookAtDist = (fDistSqr < m_cs.fHUDLookAtDist * m_cs.fHUDLookAtDist);
	bool	bWithinAlwaysOnDist = (fDistSqr < m_cs.fHUDAlwaysOnDist * m_cs.fHUDAlwaysOnDist);

	if( !bWithinLookAtDist && !bWithinAlwaysOnDist )
	{
		// We are not close enough...
		
		m_bWithinIndicatorRadius = false;
		return;
	}

	m_bWithinIndicatorRadius = true;

	g_pPhysicsLT->GetObjectDims( hPlayerObj, &vPlayerDims );

	LTVector vTrigMin = vTrigPos - m_cs.vDims;
	LTVector vTrigMax = vTrigPos + m_cs.vDims;
	LTVector vPlayerMin = vPlayerPos - vPlayerDims;
	LTVector vPlayerMax = vPlayerPos + vPlayerDims;

	// Check if we are within the height of the trigger...

	bool bWithinHeight =false;
	if( vPlayerMax.y > vTrigMin.y && vPlayerMin.y < vTrigMax.y )
		bWithinHeight = true;
	
	// See if we are inside the trigger at all...

	if( bWithinHeight && (BoxesIntersect( vTrigMin, vTrigMax, vPlayerMin, vPlayerMax ) || bWithinAlwaysOnDist))
	{
		m_fDistPercent = 1.0f;
	}
	else
	{
		// We are within the height of the trigger, show how far from it we are...

		float fMinDist = (vPlayerDims.x + vPlayerDims.z) * 0.5f;
		float fMaxDist = 100000.0f;

		LTVector vDir;

		if( bWithinAlwaysOnDist )
		{
			vDir = vTrigPos - vPlayerPos;
			vDir.Normalize();
		}
		else
		{
			LTRotation const& rRot = g_pPlayerMgr->GetPlayerCamera()->GetCameraRotation( );
			vDir = rRot.Forward();
		}

		IntersectQuery IQuery;
		IntersectInfo IInfo;

		IQuery.m_From		= vPlayerPos + (vDir * fMinDist);
		IQuery.m_To			= IQuery.m_From + (vDir * fMaxDist);
		IQuery.m_Flags		= INTERSECT_OBJECTS | INTERSECT_HPOLY | IGNORE_NONSOLID;
				
		// We need to recieve rayhits for this intersect call...

		g_pCommonLT->SetObjectFlags( m_hDimsObject, OFT_Flags, FLAG_RAYHIT, FLAG_RAYHIT );

		if( g_pLTClient->IntersectSegment( IQuery, &IInfo ))
		{
			if( IInfo.m_hObject == m_hDimsObject )
			{
				IInfo.m_Point.y = vPlayerPos.y;
				float fDist = vPlayerPos.Dist( IInfo.m_Point );
				m_fDistPercent = 1.0f - (fDist / fMaxRadius);
			}
		}

		// No more rayhits...
		
		g_pCommonLT->SetObjectFlags( m_hDimsObject, OFT_Flags, 0, FLAG_RAYHIT );
	}
}
Esempio n. 9
0
	void Execute(scriptID id, ScriptStack& scriptState)
	{
		Script script = scripts[id];
		Script::const_iterator ins = script.begin();
		Script::const_iterator end = script.end();
		for (; ins != end; ++ins)
		{
			switch(ins->GetCode())
			{
			/////////////////////////////////////////////////////////////////////////////
			case op_noop:
				break;

			case op_push:
				{
					const unsigned char* data = ins->GetData();
					ptr size = *(ptr*)data; // SIZE MISMATCH, fix it ppeas Phil
					unsigned char* value = (unsigned char*)DataAtOffset(data, 1);
					scriptState.push(value, size);
				}

				break;
			/////////////////////////////////////////////////////////////////////////////
			case op_end:
				return;
				break;

			/////////////////////////////////////////////////////////////////////////////
			case op_forceout:
				{
					// figure out our overlap and how much we have.
					const unsigned char* data = ins->GetData();
					Actor* target = GetActor(scriptState.get(*data));
					Actor* source = GetActor( scriptState.get(*DataAtOffset(data, 1)) );
					const Box* sourceBox = source->GetCollision();
					const Box* targetBox = target->GetCollision();

					if ( !BoxesIntersect(sourceBox, targetBox) )
					{
						return;
					}

					float x1, x2, x3, x4, y1, y2, y3, y4;

					x1 = sourceBox->GetUpperLeft().x;
					x2 = targetBox->GetUpperRight().x;

					x3 = sourceBox->GetUpperRight().x;
					x4 = targetBox->GetUpperLeft().x;

					y1 = sourceBox->GetLowerLeft().y;
					y2 = targetBox->GetUpperLeft().y;

					y3 = sourceBox->GetUpperLeft().y;
					y4 = targetBox->GetLowerLeft().y;

					float bottomOverlap = y1-y2+COLLISION_PADDING;
					float topOverlap = y3-y4-COLLISION_PADDING;

					float leftOverlap = x1-x2-COLLISION_PADDING;
					float rightOverlap = x3-x4+COLLISION_PADDING;

					float moveY = abs(topOverlap) > abs(bottomOverlap) ? bottomOverlap : topOverlap;
					float moveX = abs(leftOverlap) > abs(rightOverlap) ? rightOverlap : leftOverlap;

					Vector2 moveFirst, moveSecond;

					if (abs(moveX) < abs(moveY))
					{
						moveFirst.x = moveX;
						moveSecond.y = moveY;
					}
					else
					{
						moveFirst.y = moveY;
						moveSecond.x = moveX;
					}

					target->Move(moveFirst);

					if ( BoxesIntersect(sourceBox, targetBox) )
					{
						target->Move(moveSecond);
					}
				}
				break;
			/////////////////////////////////////////////////////////////////////////////
			case op_playanim:
				{
					const unsigned char* data = ins->GetData();
					Actor* target = GetActor(scriptState.get(*data));
					unsigned char animName = (unsigned char)*( DataAtOffset(data, 1) );
					target->GetAnimComponent()->PlayAnim((char*)scriptState.get(animName));
				}
				break;

			/////////////////////////////////////////////////////////////////////////////
			case op_kill:
				const unsigned char* data = ins->GetData();
				Actor* target = (Actor*) scriptState.get(*(unsigned int*)data);
				target->MarkForCleanup();
				break;

			} // end switch(instruction)
		} // end for
	} // end Execute