Exemplo n.º 1
0
bool WorldModel::CreateServerMark(CLIENTWEAPONFX & theStruct)
{
	// See if we should create a mark, or simply move one of the GameBase's
	// marks.

	// If the GameBase has the max number of marks or this mark is very close
	// to a pre-existing mark, just move that mark to the new position.

    HOBJECT hMoveObj = LTNULL;
    HOBJECT hFarObj  = LTNULL;

    uint32 nNumMarks = m_MarkList.size( );

    LTFLOAT  fClosestMarkDist  = REGION_DIAMETER;
    LTFLOAT  fFarthestMarkDist = 0.0f;
    uint8   nNumInRegion      = 0;
    LTVector vPos;

	for( ObjRefNotifierList::iterator iter = m_MarkList.begin( ); iter != m_MarkList.end( ); iter++ )
	{
		HOBJECT hObj = *iter;
		if( !hObj )
			continue;

		HATTACHMENT hAttachment = NULL;
        if (LT_OK == g_pLTServer->FindAttachment( m_hObject, hObj, &hAttachment))
		{
			LTransform transform;
            g_pCommonLT->GetAttachmentTransform(hAttachment, transform, LTTRUE);

			vPos = transform.m_Pos;
		}

        LTFLOAT fDist = VEC_DISTSQR(vPos, theStruct.vPos);
		if (fDist < REGION_DIAMETER)
		{
			if (fDist < fClosestMarkDist)
			{
				fClosestMarkDist = fDist;
				hMoveObj = hObj;
			}

			if (++nNumInRegion > MAX_MARKS_IN_REGION)
			{
				// Just move this mark to the correct pos...
				hMoveObj = hMoveObj ? hMoveObj : hObj;
				break;
			}
		}

		if (fDist > fFarthestMarkDist)
		{
			fFarthestMarkDist = fDist;
			hFarObj = hObj;
		}
	}

	// If we've got the max number of marks on this object, just move
	// the closest one to the new position...

	if (nNumMarks >= MAX_MARKS_PER_OBJECT)
	{
		if( !hMoveObj )
		{
			if( hFarObj )
			{
				hMoveObj = hFarObj;
			}
			else
			{
				HOBJECT hFirstMark = *m_MarkList.begin( );
				hMoveObj = hFirstMark;
			}
		}
	}
	else
	{
        hMoveObj = LTNULL; // Need to create one...
	}

	// Re-setup the object to move it...

	if (hMoveObj && IsKindOf(hMoveObj, "CServerMark"))
	{
        CServerMark* pMoveMark = (CServerMark*) g_pLTServer->HandleToObject(hMoveObj);
		if (!pMoveMark)
			return false;

		// Since this mark is already attached to us, remove the attachment
		DetachObject( pMoveMark->m_hObject );

		if( !AttachServerMark( *pMoveMark, (CLIENTWEAPONFX)theStruct))
		{
			g_pLTServer->RemoveObject( pMoveMark->m_hObject );
			RemoveMarkFromList( pMoveMark->m_hObject );
			pMoveMark = NULL;
			return false;
		}

		return true;
	}


	// Okay, no luck, need to create a new mark...

	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);

    LTFLOAT fScaleAdjust = 1.0f;
	if (!GetImpactSprite((SurfaceType)theStruct.nSurfaceType, fScaleAdjust,
		theStruct.nAmmoId, createStruct.m_Filename, ARRAY_LEN(createStruct.m_Filename)))
	{
		return false;
	}

	createStruct.m_ObjectType = OT_SPRITE;
	createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATEABLESPRITE;
	createStruct.m_Pos = theStruct.vPos;

	createStruct.m_Rotation = LTRotation(theStruct.vSurfaceNormal, LTVector(0.0f, 1.0f, 0.0f));

	AMMO const *pAmmo = g_pWeaponMgr->GetAmmo(theStruct.nAmmoId);
	if( !pAmmo ) 
		return false;

    static HCLASS hClass = g_pLTServer->GetClass("CServerMark");
    CServerMark* pMark = (CServerMark*) g_pLTServer->CreateObject(hClass, &createStruct);
	if (!pMark)
		return false;


	// Randomly adjust the mark's scale to add a bit o spice...

	if (pAmmo->pImpactFX)
	{
        LTFLOAT fScale = fScaleAdjust * pAmmo->pImpactFX->fMarkScale;

        LTVector vScale(fScale, fScale, fScale);
        g_pLTServer->ScaleObject(pMark->m_hObject, &vScale);
	}

	if( !AttachServerMark( *pMark, (CLIENTWEAPONFX)theStruct))
	{
		g_pLTServer->RemoveObject( pMark->m_hObject );
		pMark = NULL;
		return false;
	}

	AddMarkToList( pMark->m_hObject );

	return true;
}
static void CreateServerMark(CLIENTWEAPONFX & theStruct)
{
	AMMO* pAmmo = g_pWeaponMgr->GetAmmo(theStruct.nAmmoId);
	if (!pAmmo) return;

	// If this isn't a GameBase object, return...

	if (!IsGameBase(theStruct.hObj)) return;

	// See if we should create a mark, or simply move one of the GameBase's
	// marks.

	// If the GameBase has the max number of marks or this mark is very close
	// to a pre-existing mark, just move that mark to the new position.

    GameBase* pObj = (GameBase*) g_pLTServer->HandleToObject(theStruct.hObj);
	if (!pObj) return;

    HOBJECT hMoveObj = LTNULL;
    HOBJECT hFarObj  = LTNULL;

	ObjectList* pMarkList = pObj->GetMarkList();
	if (pMarkList)
	{
        uint8 nNumMarks = pMarkList->m_nInList;
		ObjectLink* pLink = pMarkList->m_pFirstLink;

        LTFLOAT  fClosestMarkDist  = REGION_DIAMETER;
        LTFLOAT  fFarthestMarkDist = 0.0f;
        uint8   nNumInRegion      = 0;
        LTVector vPos;

		for (int i=0; i < nNumMarks && pLink; i++)
		{
			if (pLink->m_hObject)
			{
				HATTACHMENT hAttachment;
                if (LT_OK == g_pLTServer->FindAttachment(theStruct.hObj, pLink->m_hObject, &hAttachment))
				{
					LTransform transform;
                    g_pLTServer->Common()->GetAttachmentTransform(hAttachment, transform, LTTRUE);

					vPos = transform.m_Pos;
				}

                LTFLOAT fDist = VEC_DISTSQR(vPos, theStruct.vPos);
				if (fDist < REGION_DIAMETER)
				{
					if (fDist < fClosestMarkDist)
					{
						fClosestMarkDist = fDist;
						hMoveObj = pLink->m_hObject;
					}

					if (++nNumInRegion > MAX_MARKS_IN_REGION)
					{
						// Just move this mark to the correct pos...
						hMoveObj = hMoveObj ? hMoveObj : pLink->m_hObject;
						break;
					}
				}

				if (fDist > fFarthestMarkDist)
				{
					fFarthestMarkDist = fDist;
					hFarObj = pLink->m_hObject;
				}
			}

			pLink = pLink->m_pNext;
		}

		// If we've got the max number of marks on this object, just move
		// the closest one to the new position...

		if (nNumMarks >= MAX_MARKS_PER_OBJECT)
		{
			hMoveObj = hMoveObj ? hMoveObj : (hFarObj ? hFarObj : pMarkList->m_pFirstLink->m_hObject);
		}
		else
		{
            hMoveObj = LTNULL; // Need to create one...
		}
	}

	// Re-setup the object to move it...

	if (hMoveObj && IsKindOf(hMoveObj, "CServerMark"))
	{
        CServerMark* pMoveMark = (CServerMark*) g_pLTServer->HandleToObject(hMoveObj);
		if (!pMoveMark) return;

		// Since this mark is already attached to pObj, remove the attachment
		// (since CServerMark::Setup() will re-attach it)...

		HATTACHMENT hAttachment;
        if (LT_OK == g_pLTServer->FindAttachment(theStruct.hObj, hMoveObj, &hAttachment))
		{
            g_pLTServer->RemoveAttachment(hAttachment);
		}

        pMoveMark->Setup((CLIENTWEAPONFX)theStruct);
		return;
	}


	// Okay, no luck, need to create a new mark...

	ObjectCreateStruct createStruct;
	INIT_OBJECTCREATESTRUCT(createStruct);

    LTFLOAT fScaleAdjust = 1.0f;
	if (!GetImpactSprite((SurfaceType)theStruct.nSurfaceType, fScaleAdjust,
		theStruct.nAmmoId, createStruct.m_Filename, ARRAY_LEN(createStruct.m_Filename)))
	{
		return;
	}

	createStruct.m_ObjectType = OT_SPRITE;
	createStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATEABLESPRITE;
	createStruct.m_Pos = theStruct.vPos;

    g_pLTServer->AlignRotation(&(createStruct.m_Rotation), &((LTVector)theStruct.vSurfaceNormal), LTNULL);


    HCLASS hClass = g_pLTServer->GetClass("CServerMark");
    CServerMark* pMark = (CServerMark*) g_pLTServer->CreateObject(hClass, &createStruct);
	if (!pMark) return;

	// Add the mark to the object...

	pObj->AddMark(pMark->m_hObject);


	// Randomly adjust the mark's scale to add a bit o spice...

	if (pAmmo->pImpactFX)
	{
        LTFLOAT fScale = fScaleAdjust * pAmmo->pImpactFX->fMarkScale;

        LTVector vScale;
		VEC_SET(vScale, fScale, fScale, fScale);
        g_pLTServer->ScaleObject(pMark->m_hObject, &vScale);
	}

	pMark->Setup((CLIENTWEAPONFX)theStruct);
}