Beispiel #1
0
void CDestructibleModel::RegisterDestroyedStimulus()
{
	// Register audio and visual stimulus if specified.

	if( (m_nDestroyAlarmLevel > 0) && (m_fStimRadius > 0.f) )
	{
		LTVector vPos;
		g_pLTServer->GetObjectPos(m_hObject, &vPos);

		// Extract who caused an explosion.

		HOBJECT hDamager = m_hLastDamager;
		if( IsExplosion( hDamager ) )
		{
			Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(m_hLastDamager);
			hDamager = pExplosion->GetFiredFrom();
		}

		// If damager is still not a character (possibly because an explosion was triggered), assume player.
		// Better solution - set the alignment of the damager on the explosion?

		if( !IsCharacter( hDamager ) )
		{
			CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer();
			if ( pPlayer )
			{
				hDamager = pPlayer->m_hObject;
			}
		}

		if ( IsCharacter(hDamager) )
		{
			CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hDamager);
			if ( pCharacter )
			{
				// Register the disturbance sound.

				StimulusRecordCreateStruct DisturbanceSoundSCS( kStim_DisturbanceSound, pCharacter->GetAlignment(), vPos, hDamager );
				DisturbanceSoundSCS.m_hStimulusTarget = m_hObject;
				DisturbanceSoundSCS.m_flAlarmScalar = (float)m_nDestroyAlarmLevel;
				DisturbanceSoundSCS.m_flRadiusScalar = m_fStimRadius;
				g_pAIStimulusMgr->RegisterStimulus( DisturbanceSoundSCS );

				// Register the visible disturbance.

				StimulusRecordCreateStruct DisturbanceVisibleSCS( kStim_DisturbanceVisible, pCharacter->GetAlignment(), vPos, hDamager );
				DisturbanceVisibleSCS.m_hStimulusTarget = m_hObject;
				DisturbanceVisibleSCS.m_flAlarmScalar = (float)(m_nDestroyAlarmLevel + 1);
				DisturbanceVisibleSCS.m_flRadiusScalar = m_fStimRadius;
				m_eStimID = g_pAIStimulusMgr->RegisterStimulus( DisturbanceVisibleSCS );
			}
		}
	}
}
Beispiel #2
0
void TextFont::EndChar()
{
	pivotPoint[0] += charWidth[currentChar] * halfScale[0];
	// Row finished?
	if (IsCharacter(nextChar))
		pivotPoint[0] += padding[0];
}
Beispiel #3
0
void singleclick(Network::Client* client, u32 serial)
{
  passert_always(client != nullptr && client->chr != nullptr);

  if (IsCharacter(serial))
  {
    Mobile::Character* chr = nullptr;
    if (serial == client->chr->serial)
      chr = client->chr;
    else
      chr = find_character(serial);

    if (chr != nullptr && inrange(client->chr, chr) && !client->chr->is_concealed_from_me(chr))
    {
      if (chr->has_title_guild() && (settingsManager.ssopt.core_handled_tags & 0x1))
        send_nametext(client, chr, "[" + chr->title_guild() + "]");
      send_nametext(client, chr, chr->name());

      std::string tags = create_nametags(chr);
      if (!tags.empty())
        send_nametext(client, chr, tags);
    }
  }
  else // single clicked on an item
  {
    Items::Item* item = find_legal_singleclick_item(client->chr, serial);
    if (item)
    {
      send_objdesc(client, item);
    }
  }
}
Beispiel #4
0
LTVector CAIWeaponMelee::GetFirePosition(CAI* pAI)
{
	// Force fire position to come from the edge of the target's radius.
	// This should ensure a successful melee hit.

	if( pAI && m_bForceHit )
	{
		HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();
		if( IsCharacter( hTarget ) )
		{
			LTVector vTargetPos;
			g_pLTServer->GetObjectPos( hTarget, &vTargetPos );

			LTVector vDir = vTargetPos - pAI->GetPosition();
			vDir.Normalize();

			CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject( hTarget );
			LTVector vFirePos = vTargetPos - ( vDir * pChar->GetRadius() );

			return vFirePos;
		}
	}

	// Default behavior.

	return DefaultGetFirePosition(pAI);
}
LTBOOL CAISenseSeeEnemyFootprint::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta)
{
	if ( !IsCharacter(hStimulus) ) return LTFALSE;

	CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus);

	CTList<CharFootprintInfo*>* plistFootprints = pChar->GetFootprints();

	CharFootprintInfo** ppFootprint = plistFootprints->GetItem(TLIT_FIRST);
	while ( ppFootprint && *ppFootprint )
	{
		CharFootprintInfo* pFootprint = *ppFootprint;

        if ( m_pAI->IsPositionVisibleFromEye(CAI::DefaultFilterFn, NULL, pFootprint->vPos, (m_fDistanceSqr), LTTRUE) )
		{
			React();

			// Record the Timestamp

			m_fTimestamp = pFootprint->fTimeStamp;

            return LTTRUE;
		}

		ppFootprint = plistFootprints->GetItem(TLIT_NEXT);
	}

    return LTFALSE;
}
LTBOOL CAISenseHearEnemyDisturbance::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta)
{
	if ( !IsCharacter(hStimulus) ) return LTFALSE;

    CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus);

	CharCoinInfo info;
	pChar->GetLastCoinInfo(info);

	if ( /*info.fTime > m_fStimulationTime &&*/
         g_pLTServer->GetTime() > info.fTime &&
         g_pLTServer->GetTime() < info.fTime + 0.50f )
	{
        LTFLOAT fDistance = VEC_DIST(info.vPosition, m_pAI->GetPosition());
        LTFLOAT fCoinNoiseDistance = g_pAIButeMgr->GetSenses()->fCoinNoiseDistance;
		fCoinNoiseDistance *= info.fVolume;

		if ( fDistance < (m_fDistance + fCoinNoiseDistance) )
		{
			React();

			// Record the Timestamp

			m_fTimestamp = info.fTime;

			// Record the stimulus position

			m_vStimulusPosition = info.vPosition;

            return LTTRUE;
		}
	}

    return LTFALSE;
}
void CDestructibleModel::RegisterDestroyedStimulus()
{
	// Register audio and visual stimulus if specified.

	if( (m_nDestroyAlarmLevel > 0) && (m_fStimRadius > 0.f) )
	{
		LTVector vPos;
		g_pLTServer->GetObjectPos(m_hObject, &vPos);

		// Extract who caused an explosion.

		HOBJECT hDamager = m_hLastDamager;
		if( IsExplosion( hDamager ) )
		{
			Explosion* pExplosion = (Explosion*)g_pLTServer->HandleToObject(m_hLastDamager);
			hDamager = pExplosion->GetFiredFrom();
		}

		// If damager is still not a character (possibly because an explosion was triggered), assume player.
		// Better solution - set the alignment of the damager on the explosion?

		if( !IsCharacter( hDamager ) )
		{
			CPlayerObj *pPlayer = g_pCharacterMgr->FindPlayer();
			if ( pPlayer )
			{
				hDamager = pPlayer->m_hObject;
			}
		}

		g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceSound, m_nDestroyAlarmLevel, hDamager, m_hObject, vPos, m_fStimRadius );
		m_eStimID = g_pAIStimulusMgr->RegisterStimulus( kStim_EnemyDisturbanceVisible, m_nDestroyAlarmLevel + 1, hDamager, m_hObject, vPos, m_fStimRadius );
	}
}
LTBOOL CProjectile::TestInsideObject(HOBJECT hTestObj, AmmoType eAmmoType)
{
    if (!hTestObj) return LTFALSE;

	// TO DO???
	// NOTE:  This code may need to be updated to use test the dims
	// of the CharacterHitBox instead of the dims of the object...
	// TO DO???

	// See if we are inside the test object...

    LTVector vTestPos, vTestDims;
    g_pLTServer->GetObjectPos(hTestObj, &vTestPos);
    g_pLTServer->GetObjectDims(hTestObj, &vTestDims);

	if (m_vFirePos.x < vTestPos.x - vTestDims.x ||
		m_vFirePos.x > vTestPos.x + vTestDims.x ||
		m_vFirePos.y < vTestPos.y - vTestDims.y ||
		m_vFirePos.y > vTestPos.y + vTestDims.y ||
		m_vFirePos.z < vTestPos.z - vTestDims.z ||
		m_vFirePos.z > vTestPos.z + vTestDims.z)
	{
        return LTFALSE;
	}


	// We're inside the object, so we automatically hit the object...

	if (eAmmoType == PROJECTILE)
	{
		Detonate(hTestObj);
	}
	else
	{
		if (eAmmoType == VECTOR)
		{
			if (IsCharacter(hTestObj))
			{
                CCharacter *pChar = (CCharacter*) g_pLTServer->HandleToObject(hTestObj);
                if (!pChar) return LTFALSE;

				ModelNode eModelNode = g_pModelButeMgr->GetSkeletonDefaultHitNode(pChar->GetModelSkeleton());

				pChar->SetModelNodeLastHit(eModelNode);

				m_fInstDamage *= pChar->ComputeDamageModifier(eModelNode);
			}

			ImpactDamageObject(m_hFiredFrom, hTestObj);
		}

        LTVector vNormal(0, 1, 0);
		AddImpact(hTestObj, m_vFlashPos, vTestPos, vNormal, GetSurfaceType(hTestObj));
	}

	RemoveObject();

    return LTTRUE;
}
Beispiel #9
0
bool IsDeadCharacter(  HOBJECT hObject )
{
	if( !hObject ) return true;

	if( !IsCharacter( hObject ) ) return false;

	CCharacter *pCharacter = (CCharacter*)g_pLTServer->HandleToObject( hObject );
	return ( pCharacter->GetDestructible()->IsDead() );
}
void cbStyledTextCtrl::DoBraceCompletion(const wxChar& ch)
{
    const int pos   = GetCurrentPos();
    const int style = GetStyleAt(pos);
    if (IsComment(style) || IsComment(GetStyleAt(pos - 2)))
        return; // do nothing
    if (ch == wxT('\'') || ch == wxT('"'))
    {
        if (GetCharAt(pos) == ch)
        {
            DeleteBack();
            CharRight();
        }
        else if (!IsString(GetStyleAt(pos - 2)) && !IsCharacter(GetStyleAt(pos - 2)))
            InsertText(pos, ch);
        return; // done
    }

    if (IsString(style) || IsCharacter(style))
        return; // do nothing

    const wxString opBraces(wxT("([{")); const int opBraceIdx = opBraces.Find(ch);
    const wxString clBraces(wxT(")]}")); const int clBraceIdx = clBraces.Find(ch);
    if ( (opBraceIdx != wxNOT_FOUND) || (clBraceIdx != wxNOT_FOUND) )
    {
        if ( GetCharAt(pos) == ch )
        {
            DeleteBack();
            CharRight();
        }
        else if (opBraceIdx != wxNOT_FOUND)
        {
            int nextPos = pos;
            while ( wxIsspace(GetCharAt(nextPos)) && (nextPos < GetLength()) )
                ++nextPos;

            if (   ((wxChar)GetCharAt(nextPos) != clBraces[opBraceIdx])
                || (BraceMatch(nextPos)        != wxNOT_FOUND) )
            {
                InsertText(pos, clBraces[opBraceIdx]);
            }
        }
    }
}
bool cbStyledTextCtrl::AllowTabSmartJump()
{
    const int pos = GetCurrentPos();
    if (pos == wxSCI_INVALID_POSITION)
        return false;

    const int style = GetStyleAt(pos);
    if (IsString(style) || IsCharacter(style) || IsComment(style) || IsPreprocessor(style))
        return !m_tabSmartJump;
    return true;
}
Beispiel #12
0
void CCoin::RotateToRest()
{
	if ( !m_bRotatedToRest )
	{
		char szSpawn[1024];
		sprintf(szSpawn, "WeaponItem Gravity 0;AmmoAmount 1;WeaponType Coin;AmmoType Coin");

		LTVector vPos;
		g_pLTServer->GetObjectPos(m_hObject, &vPos);
		vPos.y += 2.0f; // This offsets us from the floor a bit so we don't pop through when WeaponItem sets its dims.

		LTRotation rRot;
		rRot.Init();

		BaseClass* pObj = SpawnObject(szSpawn, vPos, rRot);

		if ( pObj && pObj->m_hObject )
		{
			g_pLTServer->SetAcceleration(pObj->m_hObject, &LTVector(0,0,0));
			g_pLTServer->SetVelocity(pObj->m_hObject, &LTVector(0,0,0));
		}

		g_pLTServer->SetObjectFlags(m_hObject, g_pLTServer->GetObjectFlags(m_hObject)&~FLAG_VISIBLE);
	}

	CGrenade::RotateToRest();

	if ( IsCharacter(m_hFiredFrom) )
	{
		LTVector vPosition;
        g_pLTServer->GetObjectPos(m_hObject, &vPosition);

        CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(m_hFiredFrom);

		CharCoinInfo cinfo;
        cinfo.fTime = g_pLTServer->GetTime();
		cinfo.eSurfaceType = m_eLastHitSurface;
		cinfo.vPosition = vPosition;

		SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface);
		_ASSERT(pSurf);
		if (pSurf)
		{
			cinfo.fVolume = pSurf->fMovementNoiseModifier;
		}
		else
		{
			cinfo.fVolume = 1.0f;
		}

		pCharacter->SetLastCoinInfo(&cinfo);
	}
}
Beispiel #13
0
void Ladder::UpdatePhysics(ContainerPhysics* pCPStruct)
{
    ILTServer* pServerDE = GetServerDE();
	if (!pServerDE) return;

	if (IsCharacter(pCPStruct->m_hObject))
	{
		CCharacter* pCharacter = (CCharacter*)pServerDE->HandleToObject(pCPStruct->m_hObject);
		if (pCharacter)
		{
			pCharacter->UpdateOnLadder(this, pCPStruct);
		}
	}
}
void CAIGoalAbstractSearch::SetStateSearch()
{
	// Reset default senses, except for SeeAllyDisturbance.

	m_pAI->SetCurSenseFlags( 0xffffffff & ~kSense_SeeAllyDisturbance );

	// Cannot search without a weapon.

	CAIHuman* pAIHuman = (CAIHuman*)m_pAI;
	if( !pAIHuman->GetCurrentWeapon() )
	{
		m_pGoalMgr->LockGoal(this);
		m_pAI->SetState( kState_HumanDraw );
		return;
	}

	// Start searching.

	m_pAI->SetState( kState_HumanSearch );
	if( IsCharacter( m_hStimulusSource ) )
	{
		m_pAI->Target(m_hStimulusSource);
	}

	m_pGoalMgr->LockGoal(this);

	CAIHumanStateSearch* pSearchState = (CAIHumanStateSearch*)m_pAI->GetState();
	if( pSearchState )
	{
		pSearchState->SetPause(LTTRUE);
		pSearchState->SetEngage(m_bEngageSearch);
		pSearchState->SetFace(m_bFaceSearch);

		// If any optional search regions have been specified, search them.
		// Otherwise, search the AIs current region.

		if( !m_lstRegions.empty() )
		{
			AIRegion* pRegion = (AIRegion*)g_pLTServer->HandleToObject( m_lstRegions.front() );
			if( pRegion )
			{
				AITRACE( AIShowGoals, ( m_pAI->m_hObject, "Searching region %s", pRegion->GetName() ) );
			}

			pSearchState->SetDestRegion( m_lstRegions.front() );
			m_lstRegions.erase( m_lstRegions.begin() );
		}
	}
}
Beispiel #15
0
ENUM_NMPolyID CAISensorPassTarget::GetTargetNavMeshPoly() 
{
	// Target is not a character.

	HOBJECT hTarget = m_pAI->GetAIBlackBoard()->GetBBTargetObject();
	if( !IsCharacter( hTarget ) )
	{
		return kNMPoly_Invalid;
	}

	// Return character's NavMesh poly.

	CCharacter* pTargetChar = (CCharacter*)g_pLTServer->HandleToObject( hTarget );
	return pTargetChar->GetCurrentNavMeshPoly();
}
LTBOOL CAISenseHearAllyPain::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta)
{
	if ( !IsCharacter(hStimulus) ) return LTFALSE;

	// Don't react to our own pain

	if ( hStimulus == GetAI()->GetObject() ) return LTFALSE;

	// See if we can hear the pain

    CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus);

	// Time has got to be greater than the pain noise time but not too much greater

	LTFLOAT fTime = g_pLTServer->GetTime();

    if ( (fTime > pChar->GetLastPainTime()) && (fTime < pChar->GetLastPainTime() + 1.0f) )
	{
		// Noise has to be within audible radius

        LTVector vPainPos;
        g_pLTServer->GetObjectPos(hStimulus, &vPainPos);

        LTFLOAT fDistance = VEC_DIST(vPainPos, m_pAI->GetPosition());
        LTFLOAT fPainNoiseDistance = g_pAIButeMgr->GetSenses()->fAllyPainNoiseDistance;
		fPainNoiseDistance *= pChar->GetLastPainVolume();

		if ( fDistance < (m_fDistance + fPainNoiseDistance) )
		{
			React();

			// Record the Timestamp

			m_fTimestamp = pChar->GetLastPainTime();

			// Record the stimulus position

			m_vStimulusPosition = vPainPos;

            return LTTRUE;
		}
	}

    return LTFALSE;
}
Beispiel #17
0
bool CAIWeaponMelee::GetShootPosition( CAI* pAI, AimContext& Context, LTVector& outvShootPos )
{
	// Force AI to aim directly at the target.

	if( pAI && m_bForceHit )
	{
		HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();
		if( IsCharacter( hTarget ) )
		{
			g_pLTServer->GetObjectPos( hTarget, &outvShootPos );
			return true;
		}
	}

	// Default behavior.

	return super::GetShootPosition( pAI, Context, outvShootPos );
}
Beispiel #18
0
Ref * sysIsUpperCase( Ref * pc, class MachineClass * vm ) {
    if ( vm->count != 1 ) throw Ginger::Mishap( "Wrong number of arguments" );
    
    Ref r = vm->fastPeek();
    if ( IsCharacter( r ) ) {
        vm->fastPeek() = isupper( CharacterToChar( r ) ) ? SYS_TRUE : SYS_FALSE;
    } else if ( IsString( r ) ) {
        Ref * str_K = RefToPtr4( r );
        char * s = reinterpret_cast< char * >( &str_K[ 1 ] );
        vm->fastPeek() = SYS_TRUE;
        while ( *s != 0 ) {
            if ( not isupper( *s++ ) ) {
                vm->fastPeek() = SYS_FALSE;
                break;
            }
        }
    } else {
        throw Ginger::Mishap( "Non-character argument" ).culprit( "Argument", refToShowString( r ) );  
    }     
    return pc;
}
LTBOOL CAISenseHearEnemyWeaponFire::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta)
{
 	if ( !IsCharacter(hStimulus) ) return LTFALSE;

	CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus);

	CharFireInfo info;
	pChar->GetLastFireInfo(info);

	// Make sure this is a recent firing of the weapon...

    if (info.fTime + 1.0 < g_pLTServer->GetTime() || info.nWeaponId == WMGR_INVALID_ID) return LTFALSE;

	WEAPON* pWeapon = g_pWeaponMgr->GetWeapon(info.nWeaponId);
    if (!pWeapon) return LTFALSE;

	// Get the Distance that fire noise carries

    LTFLOAT fWeaponFireNoiseDistance = (LTFLOAT)pWeapon->nAIFireSoundRadius;
	if (info.bSilenced) fWeaponFireNoiseDistance *= 0.25f;

	// Get the distance from the fire

    LTFLOAT fDistance  = VEC_DIST(info.vFiredPos, m_pAI->GetPosition());

	// Are we close enough to hear?

	if ( fDistance < (m_fDistance + fWeaponFireNoiseDistance) )
	{
		React();

		// Record the Timestamp

		m_fTimestamp = info.fTime;

        return LTTRUE;
	}

    return LTFALSE;
}
Beispiel #20
0
int Format(char* num)
{
    int i = 0;
    int f=1000000;
    char c;
    int result = 0;
    while ((c=*(num+i))!='\0')
    {
        if (IsNum(c))
        {
            result += f*(c - '0');
            f /= 10;
        }
        if (IsCharacter(c))
        {
            result += f*(maps[c - 'A']);
            f /= 10;
        }
        i++;
    }
    return result;
}
Beispiel #21
0
void CAIWeaponAbstract::GetBlindFirePosition(CAI* pAI, LTVector& outvShootPos, bool bMiss )
{
	ASSERT(pAI);

	HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();
	if( !IsCharacter( hTarget ) )
	{
		return;
	}

	CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject( hTarget );
	if( !pChar )
	{
		return;
	}

	// Intentionally shoot a little short of the target.

	float fDist = sqrt( pAI->GetTarget()->GetTargetDistSqr() );

	float fRadius = pChar->GetRadius();
	float fRand = GetRandom( 0.f, 1.f );
	fDist -= ( fRadius * 2.f ) + ( fRand * pAI->GetAccuracyMissPerturb() );

	// Aim wherever the weapon is aiming.

	LTVector vDir = pAI->GetWeaponForward( m_pWeapon );
	outvShootPos = pAI->GetPosition() + ( vDir * fDist );

	// Force bullets to land in front of the target, on the floor.

	if( bMiss && m_pAIWeaponRecord->bForceMissToFloor )
	{
		float fFloor = pAI->GetAIBlackBoard()->GetBBTargetPosition().y;
		fFloor -= pAI->GetAIBlackBoard()->GetBBTargetDims().y;
		outvShootPos.y = fFloor;
	}
}
LTBOOL CAISenseHearEnemyFootstep::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta)
{
	if ( !IsCharacter(hStimulus) ) return LTFALSE;

    CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hStimulus);

	CharMoveInfo info;
	pChar->GetLastMoveInfo(info);

	if ( info.fTime > m_fStimulationTime &&
         g_pLTServer->GetTime() > info.fTime &&
         g_pLTServer->GetTime() < info.fTime + 0.50f )
	{
        LTVector vMovementPos;
        g_pLTServer->GetObjectPos(hStimulus, &vMovementPos);

        LTFLOAT fDistance = VEC_DIST(vMovementPos, m_pAI->GetPosition());
        LTFLOAT fMovementNoiseDistance = g_pAIButeMgr->GetSenses()->fEnemyMovementNoiseDistance;
		fMovementNoiseDistance *= info.fVolume;

		if ( fDistance < (m_fDistance + fMovementNoiseDistance) )
		{
			IncreaseStimulation(fTimeDelta);

			// Record the timestamp

			m_fTimestamp = info.fTime;

			// Record the stimulus position

			m_vStimulusPosition = vMovementPos;

            return LTTRUE;
		}
	}

    return LTFALSE;
}
Beispiel #23
0
bool CKeyMgr::CanCharacterControlObject( HOBJECT hChar, HOBJECT hObj )
{
#ifndef _CLIENTBUILD

	if( !hChar || !hObj || !IsCharacter( hChar ))
		return false;

	// If there are no keys that control this object the Character shouldn't be able to control it.
	
	KeyControlMap::iterator iter = m_mapKeyControl.find( hObj );
	if( iter == m_mapKeyControl.end() )
		return false;

	CCharacter *pChar = (CCharacter*)g_pLTServer->HandleToObject( hChar );
	if( !pChar )
		return false;

	IDList *pCharKeyList = pChar->GetKeyList();
	uint8 nDummy;

	IDList& idList = (*iter).second.m_IDList;

	// Make sure the character has all the keys that are needed to control the object...

	for( uint8 i = 0; i < idList.m_IDArray.size(); ++i )
	{
		if( !pCharKeyList->Have( idList.m_IDArray[i], nDummy ))
		{
			return false;
		}
	}

#endif

	return true;
}
Beispiel #24
0
void CAIWeaponMelee::Fire(CAI* pAI)
{
	if( !m_pWeapon )
	{
		AIASSERT( 0, pAI->GetHOBJECT(), "CAIWeaponMelee::Fire: No weapon!" );
		return;
	}

	if( m_eFiringState != kAIFiringState_Firing )
	{
		return;
	}

	// Fire!

	LTVector vTargetPos;
	bool bHit = GetShootPosition( pAI, m_Context, vTargetPos );
	if (DefaultFire(pAI, vTargetPos, m_pAIWeaponRecord->bAIAnimatesReload))
	{
		// Decrement burst count for this shot.
		m_nBurstShots--;
	}

	// Knock the player back, if the hit inflicted damage.

	if( bHit )
	{
		CPlayerObj* pPlayer = NULL;
		HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject();
		if( IsPlayer( hTarget ) )
		{
			pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject( hTarget );
		}

		if( pPlayer &&
			( m_pAIWeaponRecord->fPlayerPusherRadius > 0.f ) &&
			( m_pAIWeaponRecord->fPlayerPusherForce > 0.f ) &&
			( pPlayer->GetDestructible() ) &&
			( pPlayer->GetDestructible()->GetLastDamageTime() == g_pLTServer->GetTime() ) &&
			( pPlayer->GetDestructible()->GetLastDamager() == pAI->m_hObject ) )
		{
			if( ( pPlayer->GetDestructible()->GetLastArmorAbsorb() > 0.f ) ||
				( pPlayer->GetDestructible()->GetLastDamage() > 0.f ) )
			{
				pPlayer->PushCharacter( pAI->GetPosition(), m_pAIWeaponRecord->fPlayerPusherRadius, 0.f, 0.3f, m_pAIWeaponRecord->fPlayerPusherForce );
			}
		}

		// Only play if we've been targeting someone for at least 5 seconds.
		// This ensures we first play higher priority reaction sounds.

		if( IsCharacter( hTarget ) )
		{
			CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject( hTarget );
			if( pChar &&
				( pChar->GetDestructible() ) &&
				( pChar->GetDestructible()->GetLastDamageTime() == g_pLTServer->GetTime() ) &&
				( pChar->GetDestructible()->GetLastDamager() == pAI->m_hObject ) &&
				( pAI->GetAIBlackBoard()->GetBBTargetChangeTime() < g_pLTServer->GetTime() - 5.f ) )
			{
				HOBJECT hAlly = g_pAICoordinator->FindAlly( pAI->m_hObject, hTarget );
				if( hAlly )
				{
					g_pAISoundMgr->RequestAISound( hAlly, kAIS_HitSeenMelee, kAISndCat_Event, hTarget, 0.5f );
				}
			}
		}
	}
}
Beispiel #25
0
void CreateClientWeaponFX(CLIENTWEAPONFX & theStruct)
{
    if (!g_pLTServer) return;

	// make sure the impact FX in valid
	ASSERT( ( 0 <= theStruct.eImpactType ) || ( IMPACT_TYPE_COUNT > theStruct.eImpactType ) );

	// If this is a moveable object, set the flags of fx to ignore
	// marks and smoke...

	if (IsMoveable(theStruct.hObj))
	{
		theStruct.wIgnoreFX |= WFX_MARK;

		// Create a server-side mark if applicable...

		if (CanMarkObject(theStruct.hObj))
		{
			AMMO const *pAmmo = g_pWeaponMgr->GetAmmo(theStruct.nAmmoId);
			if (pAmmo)
			{
				if (pAmmo->pImpactFX)
				{
					if (WFX_MARK & pAmmo->pImpactFX->nFlags)
					{
                        CreateServerMark((CLIENTWEAPONFX)theStruct);
					}
				}

				// Create an exit mark if applicable...

				if (pAmmo->pFireFX)
				{
					if (WFX_EXITMARK & pAmmo->pFireFX->nFlags)
					{
						CreateServerExitMark((const CLIENTWEAPONFX)theStruct);
					}
				}
			}
		}
	}

	// Do impact dings if applicable...

	if (!(IsMultiplayerGame() && IsCharacter(theStruct.hObj)))
	{
		theStruct.wIgnoreFX |= WFX_IMPACTDING;
	}


	// [KLS 2/28/02] - If the object hit is a character, re-evaluate the surface type.
	// We do this here because the process of applying damage to the character may have
	// changed the character's surface type (e.g., from Armor to Flesh).

	if (IsCharacter(theStruct.hObj))
	{
		theStruct.nSurfaceType = GetSurfaceType(theStruct.hObj);
	}


	// Tell all the clients who can see this fx about the fx...

	CAutoMessage cMsg;
	cMsg.Writeuint8(SFX_WEAPON_ID);
	cMsg.WriteObject(theStruct.hObj);
	cMsg.WriteObject(theStruct.hFiredFrom);
    cMsg.Writeuint8(theStruct.nWeaponId);
    cMsg.Writeuint8(theStruct.nAmmoId);
    cMsg.Writeuint8(theStruct.nSurfaceType);
    cMsg.Writeuint16(theStruct.wIgnoreFX);
    cMsg.Writeuint8(theStruct.nShooterId);
    cMsg.WriteLTVector(theStruct.vFirePos);
    cMsg.WriteLTVector(theStruct.vPos);
    cMsg.WriteLTVector(theStruct.vSurfaceNormal);
    cMsg.Writeuint8(theStruct.eImpactType);
	g_pLTServer->SendSFXMessage(cMsg.Read(), theStruct.vPos, 0);
}
Beispiel #26
0
void doubleclick( Network::Client* client, PKTIN_06* msg )
{
  u32 serial = cfBEu32( msg->serial );
  u32 paperdoll_macro_flag = serial & 0x80000000Lu;
  serial &= ~0x80000000Lu;  // keypress versus doubleclick switch?

  // the find_character would find this, but most of the time it's your own paperdoll.
  // this is special-cased for two reasons:
  //    1) it's commonly done
  //    2) ghosts can doubleclick ONLY their paperdoll.
  if ( serial == client->chr->serial )
  {
    if ( !paperdoll_macro_flag )
    {
      ScriptDef sd;
      sd.quickconfig( "scripts/misc/dblclickself.ecl" );
      if ( sd.exists() )
      {
        ref_ptr<Bscript::EScriptProgram> prog;
        prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts );
        if ( prog.get() != nullptr && client->chr->start_script( prog.get(), false ) )
        {
          return;
        }
      }
    }
    send_paperdoll( client, client->chr );
    return;
  }

  if ( client->chr->dblclick_wait() > read_gameclock() )
  {
    private_say_above( client->chr, client->chr, "You must wait to use something again." );
    return;
  }
  else
    client->chr->dblclick_wait( read_gameclock() + settingsManager.ssopt.dblclick_wait );

  if ( IsCharacter( serial ) )
  {
    if ( client->chr->dead() )
      return;
    Mobile::Character* chr = find_character( serial );
    if ( !chr )
      return;

    if ( chr->isa( UOBJ_CLASS::CLASS_NPC ) )
    {
      Mobile::NPC* npc = static_cast<Mobile::NPC*>( chr );
      if ( npc->can_accept_event( EVID_DOUBLECLICKED ) )
      {
        npc->send_event( new Module::SourcedEvent( EVID_DOUBLECLICKED, client->chr ) );
        return;
      }
    }

    bool script_ran = false;
    ScriptDef sd;
    sd.quickconfig( "scripts/misc/dblclickother.ecl" );
    if ( sd.exists() )
    {
      ref_ptr<Bscript::EScriptProgram> prog;
      prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts );
      if ( prog.get() != nullptr )
        script_ran =
            client->chr->start_script( prog.get(), false, new Module::ECharacterRefObjImp( chr ) );
    }
    if ( !script_ran && inrange( client->chr, chr ) )
    {
      // MuadDib Changed from a large if || || || to switch case. 1/4/2007
      switch ( chr->graphic )
      {
      case UOBJ_HUMAN_MALE:
      case UOBJ_HUMAN_FEMALE:
      case UOBJ_HUMAN_MALE_GHOST:
      case UOBJ_HUMAN_FEMALE_GHOST:
      case UOBJ_ELF_MALE:
      case UOBJ_ELF_FEMALE:
      case UOBJ_ELF_MALE_GHOST:
      case UOBJ_ELF_FEMALE_GHOST:
      case UOBJ_GARGOYLE_MALE:
      case UOBJ_GARGOYLE_FEMALE:
      case UOBJ_GARGOYLE_MALE_GHOST:
      case UOBJ_GARGOYLE_FEMALE_GHOST:
      case UOBJ_GAMEMASTER:
      case 0x3de:
      case 0x3df:
      case 0x3e2:
        send_paperdoll( client, chr );
        break;
      }
    }
    return;
  }
  else  // doubleclicked an item
  {
    // next, search worn items, items in the backpack, and items in the world.
    Items::Item* item = find_legal_item( client->chr, serial );

    // next, check people's backpacks. (don't recurse down)
    //    (not done yet)

    if ( item != nullptr )
    {
      const Items::ItemDesc& id = item->itemdesc();

      if ( !id.ghosts_can_use && client->chr->dead() )
      {
        private_say_above( client->chr, client->chr, "I am dead and cannot do that." );
        return;
      }
      if ( !id.can_use_while_frozen && client->chr->frozen() )
      {
        private_say_above( client->chr, client->chr, "I am frozen and cannot do that." );
        return;
      }
      if ( !id.can_use_while_paralyzed && client->chr->paralyzed() )
      {
        private_say_above( client->chr, client->chr, "I am paralyzed and cannot do that." );
        return;
      }

      unsigned short dst = pol_distance( client->chr, item );
      if ( dst > id.doubleclick_range && !client->chr->can_dblclickany() )
      {
        private_say_above( client->chr, item, "That is too far away." );
        return;
      }
      UObject* obj = item->toplevel_owner();
      obj = obj->self_as_owner();
      if ( id.use_requires_los && !client->chr->realm->has_los( *client->chr, *obj ) )  // DAVE
                                                                                        // 11/24
      {
        private_say_above( client->chr, item, "I can't see that." );
        return;
      }

      ScriptDef sd;
      sd.quickconfig( "scripts/misc/dblclickitem.ecl" );
      if ( sd.exists() )
      {
        ref_ptr<Bscript::EScriptProgram> prog;
        prog = find_script2( sd, false, Plib::systemstate.config.cache_interactive_scripts );
        if ( prog.get() != nullptr )
          client->chr->start_script( prog.get(), false, new Module::EItemRefObjImp( item ) );
      }

      item->double_click( client );
      return;
    }

    // allow looking into containers being traded
    if ( client->chr->is_trading() )
    {
      UContainer* cont = client->chr->trade_container()->find_container( serial );
      if ( cont != nullptr )
      {
        cont->builtin_on_use( client );
        if ( !cont->locked() )
        {
          if ( client->chr->trading_with->client != nullptr )
            cont->builtin_on_use( client->chr->trading_with->client );
        }
        return;
      }
    }
  }
}
LTBOOL DoVectorFilterFn(HOBJECT hObj, void *pUserData)
{
	// We're not attacking our self...

	if (SpecificObjectFilterFn(hObj, pUserData))
	{
		// CharacterHitBox objects are used for vector impacts, don't
		// impact on the character/body prop object itself....

		if (IsCharacter(hObj) || IsBody(hObj) || IsKindOf(hObj, "Intelligence"))
		{
            return LTFALSE;
		}

		// Check special character hit box cases...

		if (IsCharacterHitBox(hObj))
		{
            CCharacterHitBox *pCharHitBox = (CCharacterHitBox*) g_pLTServer->HandleToObject(hObj);
			if (pCharHitBox)
			{
				// Make sure we don't hit ourself...

				HOBJECT hUs = (HOBJECT)pUserData;

				HOBJECT hTestObj = pCharHitBox->GetModelObject();
                if (!hTestObj) return LTFALSE;

				if (hTestObj == hUs)
				{
                    return LTFALSE;
				}


				// Do special AI hitting AI case...
				if (IsAI(hUs) && IsAI(hTestObj))
				{
                    CAI *pAI = (CAI*) g_pLTServer->HandleToObject(hUs);
                    if (!pAI) return LTFALSE;

					// We can't hit guys we like, unless they're NEUTRAL

                    CCharacter* pB = (CCharacter*)g_pLTServer->HandleToObject(hTestObj);
                    if (!pB) return LTFALSE;

					CharacterClass cc = pB->GetCharacterClass();
					if (cc != NEUTRAL)
					{
						return LIKE != GetAlignement(pAI->GetCharacterClass(), cc);
					}
				}

				// Check for friendly fire
				if (g_pGameServerShell->GetGameType() == COOPERATIVE_ASSAULT && g_vtNetFriendlyFire.GetFloat() < 1.0f)
				{
					// We can't hit guys on our team unless friendly fire is turned on
					if (IsPlayer(hUs) && IsPlayer(hTestObj))
					{
                        CPlayerObj* pUs = (CPlayerObj*) g_pLTServer->HandleToObject(hUs);
                        if (!pUs) return LTFALSE;


                        CPlayerObj* pThem = (CPlayerObj*) g_pLTServer->HandleToObject(hTestObj);
                        if (!pThem) return LTFALSE;

						if (pUs->GetTeamID() == pThem->GetTeamID())
                            return LTFALSE;
					}

				}
			}
		}

        return LTTRUE;
	}

    return LTFALSE;
}
void CProjectile::AddImpact(HOBJECT hObj, LTVector vFirePos, LTVector vImpactPos,
                            LTVector vSurfaceNormal, SurfaceType eType)
{
	// Create the client side weapon fx...

	CLIENTWEAPONFX fxStruct;

	fxStruct.hFiredFrom		= m_hFiredFrom;
	fxStruct.vSurfaceNormal	= vSurfaceNormal;
	fxStruct.vFirePos		= vFirePos;
	fxStruct.vPos			= vImpactPos + (m_vDir * -1.0f);
	fxStruct.hObj			= hObj;
	fxStruct.nWeaponId		= m_pWeaponData->nId;
	fxStruct.nAmmoId		= m_pAmmoData->nId;
	fxStruct.nSurfaceType	= eType;
	fxStruct.wIgnoreFX		= g_wIgnoreFX;

	// Always use the flash position for the first call to AddImpact...

	if (m_bNumCallsToAddImpact == 0)
	{
		fxStruct.vFirePos = m_vFlashPos;
	}

	// If we do multiple calls to AddImpact, make sure we only do some
	// effects once :)

	g_wIgnoreFX |= WFX_SHELL | WFX_LIGHT | WFX_MUZZLE;


	// Allow exit surface fx on the next call to AddImpact...

	g_wIgnoreFX &= ~WFX_EXITSURFACE;


	if (IsMoveable(hObj))
	{
		// Well, don't do too many exit marks...The server will add one
		// if necessary...

		g_wIgnoreFX |= WFX_EXITMARK;
	}


	// If this is a player object, get the client id...

	if (IsPlayer(m_hFiredFrom))
	{
        CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hFiredFrom);
		if (pPlayer)
		{
            fxStruct.nShooterId = (uint8) g_pLTServer->GetClientID(pPlayer->GetClient());
		}
	}

	CreateClientWeaponFX(fxStruct);

	// Do the area and progressive (over time) damage...

	if ((m_pAmmoData->nAreaDamage > 0.0f && eType != ST_SKY) ||
		 m_pAmmoData->fProgDamageLifetime > 0.0f)
	{
		AddExplosion(vImpactPos, vSurfaceNormal);
	}


	// Update Character fire info...

	if (m_hFiredFrom && IsCharacter(m_hFiredFrom) && CanSetLastFireInfo())
	{
        CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hFiredFrom);
		if (pChar)
		{
			CharFireInfo info;
			info.hObject	= hObj;
			info.vFiredPos	= m_vFlashPos;  // Use initial flash pos
			info.vImpactPos = vImpactPos;
			info.nWeaponId  = m_pWeaponData->nId;
			info.nAmmoId	= m_pAmmoData->nId;
            info.fTime      = g_pLTServer->GetTime();
			info.bSilenced  = m_bSilenced;
			info.eSurface	= eType;

			pChar->SetLastFireInfo(&info);
		}
	}

	m_bNumCallsToAddImpact++;
}
void CProjectile::HandleTouch(HOBJECT hObj)
{
	if (m_bObjectRemoved) return;

	// Don't process any touches until this has been cleared...

	if (m_bProcessInvImpact) return;

	 // Let it get out of our bounding box...

	if (hObj == m_hFiredFrom) return;

	CCharacterHitBox* pHitBox = LTNULL;

	// If we've hit a character (or body), let its hit box take control...

	if (IsCharacter(hObj))
	{
       CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj);
		if (pChar)
		{
			hObj = pChar->GetHitBox();
		}
	}
	else if (IsBody(hObj))
	{
	    Body* pBody = (Body*)g_pLTServer->HandleToObject(hObj);
		if (pBody)
		{
			hObj = pBody->GetHitBox();
		}
	}


	if (IsCharacterHitBox(hObj))
	{
        pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj);
		if (!pHitBox) return;

		if (pHitBox->GetModelObject() == m_hFiredFrom) return;
	}


	// Don't hit our own type of projectiles (for multi-projectile weapons
	// and projectiles that stick to objects)...

	if (IsKindOf(hObj, m_hObject))
	{
        CProjectile* pObj = (CProjectile*)g_pLTServer->HandleToObject(hObj);
		if (pObj)
		{
			if (pObj->GetFiredFrom() == m_hFiredFrom)
			{
				return;
			}
		}
	}



	// See if we want to impact on this object...

    uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(hObj);
	if (dwUsrFlags & USRFLG_IGNORE_PROJECTILES) return;

    LTBOOL bIsWorld = IsMainWorld(hObj);


	// Don't impact on non-solid objects...unless it is a CharacterHitBox
	// object...

    uint32 dwFlags = g_pLTServer->GetObjectFlags(hObj);
	if (!bIsWorld && !(dwFlags & FLAG_SOLID))
	{
		if (pHitBox)
		{
			// See if we really impacted on the box...

			if (pHitBox->DidProjectileImpact(this))
			{
				// This is the object that we really hit...

				hObj = pHitBox->GetModelObject();
			}
			else
			{
				return;
			}
		}
		else if (!(dwFlags & FLAG_RAYHIT))
		{
			// If we have ray hit set to true, projectiles should
			// impact on us too...

			return;
		}
	}


	// See if we hit the sky...

	if (bIsWorld || (OT_WORLDMODEL == g_pLTServer->GetObjectType(hObj)))
	{
		CollisionInfo info;
        g_pLTServer->GetLastCollision(&info);

		SurfaceType eType = GetSurfaceType(info);

		if (eType == ST_SKY)
		{
			RemoveObject();
			return;
		}
		else if (eType == ST_INVISIBLE)
		{
			// Update 1.002 [KLS] - If multiplayer and we hit an invisible
			// surface, just treat it like a normal surface...
			if (!IsMultiplayerGame())
			{
				m_bProcessInvImpact = LTTRUE;

				g_pLTServer->GetObjectPos(m_hObject, &m_vInvisNewPos);
				g_pLTServer->GetVelocity(m_hObject, &m_vInvisVel);
				m_vInvisNewPos += (m_vInvisVel * g_pLTServer->GetFrameTime());

				// Make sure this new position is inside the world...else
				// just blow up...

				if (LT_INSIDE == g_pLTServer->Common()->GetPointStatus(&m_vInvisNewPos))
				{
					return;
				}
			}
		}
	}


	HandleImpact(hObj);
}
void CProjectile::ImpactDamageObject(HOBJECT hDamager, HOBJECT hObj)
{
	DamageStruct damage;

	damage.hDamager = hDamager;
	damage.vDir		= m_vDir;

	// Do Instant damage...

	if (m_fInstDamage > 0.0f)
	{
		damage.eType	= m_eInstDamageType;
		damage.fDamage	= m_fInstDamage;

		damage.DoDamage(this, hObj);
	}

	// Do Progressive damage...(if the progressive damage is supposed to
	// happen over time, it will be done in the explosion object)....

	if (m_fProgDamage > 0.0f && m_pAmmoData->fProgDamageLifetime <= 0.0f)
	{
		damage.eType	 = m_eProgDamageType;
		damage.fDamage	 = m_fProgDamage;
		damage.fDuration = m_pAmmoData->fProgDamageDuration;

		damage.DoDamage(this, hObj);
	}



	// Update player summary info...

	CPlayerObj* pPlayer;
	if (IsPlayer(hDamager) && IsCharacter(hObj) && IsAccuracyType(m_eInstDamageType))
	{
        CCharacter* pChar = (CCharacter*) g_pLTServer->HandleToObject(hObj);
        pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hDamager);
		if (pPlayer)
		{
			ModelNode eModelNode = pChar->GetModelNodeLastHit();

			if (eModelNode != eModelNodeInvalid)
			{
				HitLocation eLoc = g_pModelButeMgr->GetSkeletonNodeLocation(pChar->GetModelSkeleton(),eModelNode);
				pPlayer->GetPlayerSummaryMgr()->IncNumHits(eLoc);
			}
			else
			{
				pPlayer->GetPlayerSummaryMgr()->IncNumHits(HL_UNKNOWN);
			}
		}
	}

	if (IsPlayer(hObj))
	{
        pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(hObj);
		if (pPlayer)
		{
			pPlayer->GetPlayerSummaryMgr()->IncNumTimesHit();
		}
	}
}