Exemple #1
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CSoundSet::GetRandomFile()
//
//	PURPOSE:	Get a random sound from the set
//
// ----------------------------------------------------------------------- //
const char* CSoundSet::GetRandomFile()
{
    //if we're not set up or we have no files, bail
    if (!m_hRecord || !m_nTotalWeight || !m_vecWeights.size())
        return "";

#if defined(PLATFORM_WIN32) || defined(PLATFORM_LINUX)
    HATTRIBUTE hFiles =	g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sSoundFile);

    //only got one, return it
    if (m_vecWeights.size() == 1)
        return g_pLTDatabase->GetString(hFiles,0,"");

    uint32 nRand = GetRandom(0,m_nTotalWeight-1);

    for (uint32 n = 0; n < m_vecWeights.size(); ++n)
    {
        if (nRand < m_vecWeights[n])
            return g_pLTDatabase->GetString(hFiles,n,"");
    }

    //if we got this far, just return the first value
    return g_pLTDatabase->GetString(hFiles,0,"");
#endif // PLATFORM_WIN32 || PLATFORM_LINUX

#ifdef PLATFORM_XENON
    HATTRIBUTE hCue = g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sXActCue);

    if (hCue)
    {
        return g_pLTDatabase->GetString(hCue,0,"");
    }
    else
    {
        return "";
    }
#endif // PLATFORM_XENON
}
Exemple #2
0
bool CMusicMgr::SetMood( Mood eMood )
{
	char szMusic[128];
	uint32 iLevel = GetRandom(0, m_acMoods[eMood]-1);
	sprintf(szMusic, "MUSIC I %d measure", m_aanMoods[eMood][iLevel]);

#ifndef _FINAL
	if ( g_ShowMusicTrack.GetFloat() > 0 )
	{
		g_pLTServer->CPrint("Server sending client Music Message: (%s)", szMusic);
	}
#endif

	HSTRING hMusic = g_pLTServer->CreateString(szMusic);
	CAutoMessage cMsg;
	cMsg.Writeuint8(MID_MUSIC);
	cMsg.WriteHString(hMusic);
	g_pLTServer->SendToClient(cMsg.Read(), LTNULL, MESSAGE_GUARANTEED);
	FREE_HSTRING(hMusic);

	m_eLastMood = eMood;
	return true;
}
Exemple #3
0
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CSoundSet::GetRandomAltFile()
//
//	PURPOSE:	Get a random alternate sound from the set
//
// ----------------------------------------------------------------------- //
const char* CSoundSet::GetRandomAltFile()
{
    //if we're not set up or we have no files, bail
    if (!m_hRecord || !m_nAltTotalWeight || !m_vecAltWeights.size())
        return "";

    HATTRIBUTE hFiles =	g_pLTDatabase->GetAttribute(m_hRecord,SndDB_sAltSoundFile);

    //only got one, return it
    if (m_vecAltWeights.size() == 1)
        return g_pLTDatabase->GetString(hFiles,0,"");

    uint32 nRand = GetRandom(0,m_nAltTotalWeight-1);

    for (uint32 n = 0; n < m_vecAltWeights.size(); ++n)
    {
        if (nRand < m_vecAltWeights[n])
            return g_pLTDatabase->GetString(hFiles,n,"");
    }

    //if we got this far, just return the first value
    return g_pLTDatabase->GetString(hFiles,0,"");
}
//
//  Translate Exposure settings into a "current value".
//
LONGLONG
CHardwareSimulation::
GetCurrentExposureTime()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    LONGLONG   Value = 0;
    LPCSTR      Mode = "[UNKNOWN]";

    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO )
    {
        //  Get random value in global setting's bound (LONG)
        //  I'm abandoning the reported min/max and using something more reasonable.
        Value = GetRandom( MIN_EXPOSURE_TIME*5, DEF_EXPOSURE_TIME*5 );
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_AUTO";
    }

    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL )
    {
        Value = pSettings->ExposureSetting.VideoProc.Value.ll;
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_MANUAL";
    }

    //  Locked just reports the last value set...
    if( pSettings->ExposureMode & KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK )
    {
        Value = m_LastReportedExposureTime;
        Mode = "KSCAMERA_EXTENDEDPROP_VIDEOPROCFLAG_LOCK";
    }

    DBG_TRACE("ExposureMode=0x%016llX (%s), Time=%llu00ns, LastReported=%llu00ns",
              pSettings->ExposureMode, Mode, Value, m_LastReportedExposureTime );

    m_LastReportedExposureTime = Value;
    return Value;
}
Exemple #5
0
SEARCH_SET::SearchObjectType SEARCH_SET::GetRandomSearchObjectType(float fJunkModifier)
{
	if (fJunkModifier < 0.0f || fJunkModifier > 1.0f)
	{
		ASSERT(!"SEARCH_SET::GetRandomSearchObjectType(): bad skill modifier");
		fJunkModifier = 1.0f;
	}

	//reduce the chance of random junk
	uint8 nJunkChance = (uint8)( (float)nItemPercent * fJunkModifier );

	//figure out a new total
	uint8 nTotal = 100 - (nItemPercent - nJunkChance);

	//roll the die...
	uint8 nRandVal = GetRandom(1, nTotal);

	SearchObjectType eType = eUnknownObjectType;
	if (nRandVal <= nJunkChance)
	{
		eType = eItemObjectType;
	}
	else if (nRandVal <= nJunkChance + nAmmoPercent)
	{
		eType = eAmmoObjectType;
	}
	else if (nRandVal <= nJunkChance + nAmmoPercent + nWeaponPercent)
	{
		eType = eWeaponObjectType;
	}
	else
	{
		eType = eGearObjectType;
	}

	return eType;
}
Exemple #6
0
	bool __CALLOUT InitializeShell() {
		Clear(BLUE);
		const char* str = "PRICE of HONOR!";
		DrawTextString(40,60,str,Length(str),RED,BLUE);
	
		GetBatteryLevel();
		SetScreenBrightness(100);
		char buff[200];
		int res = snprintf(buff,sizeof(buff),"test %d",0);
		DrawPixel(1,1,WHITE);
		DoVibroAndBeep(500);
		ubyte_t l = GetLustraId();
		SendRadioPacket(NULL,0);
		uword_t a = GetArmletId();
		FILE log;
		OpenFile(&log, "log.txt", true);
		char* s = "log test";
		WriteFile(&log, s, Length(s));	
		/*
		//int i = 0;
		//Color area[100];
		//for (i=0; i<100; i++) area[i] = 0xF0F;
		//DrawArea(5,5,area,100,10,10);
		//WriteFile(&log, (char*)area, 100);
		//for (i=0; i<100; i++) area[i] = 0x0;
		//ReadFile(&log, (char*)area, 100);
		//AppendFile(&log, (char*)area, 100);
		//DrawArea(5,5,area,100,10,10);
		*/
		RequestTimer(TimerProc,100);
		int up = GetUpTime();
		int rnd = GetRandom(50);
		//SetCureName is checked in AppMainThread
		//WritePill is checked in AppMainThread
		//StartThread(AppMainThread,NULL);
		return true; //TODO
	}
//
//  Translate ISO settings into a "current value".
//
ULONG
CHardwareSimulation::
GetCurrentISOSpeed()
{
    PAGED_CODE();

    ISP_FRAME_SETTINGS *pSettings = GetIspSettings();
    ULONG   Value = 0;

    if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_AUTO )
    {
        Value = GetRandom( (ULONG) 50, (ULONG) 3200 );
    }
    else if( pSettings->ISOMode & KSCAMERA_EXTENDEDPROP_ISO_MANUAL )
    {
        Value = pSettings->ISOValue;
    }
    else
    {
        Value =             //  Try converting any legacy presets to a manual value.
            IsoPreset2Value( pSettings->ISOMode );
    }
    return Value;
}
void Reaction::DeepCopy(Reaction& other,BehaviorSet& behaviors)
{
    desireValue            = other.desireValue;
    desireType             = other.desireType;
    for (size_t i = 0; i < other.affected.GetSize(); i++)
    {
        Behavior * behavior = behaviors.Find(other.affected[i]->GetName());
        affected.Push(behavior);
    }
    eventType              = other.eventType;
    range                  = other.range;
    factionDiff            = other.factionDiff;
    oper                   = other.oper;
    weight                 = other.weight;
    values                 = other.values;
    valuesValid            = other.valuesValid;
    randoms                = other.randoms;
    randomsValid           = other.randomsValid;
    type                   = other.type;
    activeOnly             = other.activeOnly;
    inactiveOnly           = other.inactiveOnly;
    reactWhenDead          = other.reactWhenDead;
    reactWhenInvisible     = other.reactWhenInvisible;
    reactWhenInvincible    = other.reactWhenInvincible;
    onlyInterrupt          = other.onlyInterrupt;
    doNotInterrupt         = other.doNotInterrupt;

    // For now depend on that each npc do a deep copy to create its instance of the reaction
    for (uint ii=0; ii < values.GetSize(); ii++)
    {
        if (GetRandomValid((int)ii))
        {
            values[ii] += psGetRandom(GetRandom((int)ii));
        }
    }
}
int main(int argc, char *argv[])
{
    FILE* fp;
    unsigned int i;
    
    struct data_t data;

    if (argc != 3) {
        printf("## Data Generator for 310_sort Ver.2013-10-13\n");
        printf("## Usage: ./data_gen i random_seed\n");
        printf("##      : n = i * 1024n");
        exit(1);
    }
    
    int random_seed = atoi(argv[2]);
    srand(random_seed);
    
    fp = fopen("310sort.txt", "wb");
    if (fp==NULL) { fputs("fail to open\n", stderr); exit(1); }
    
    for (i=0; i<SIZE-1; i++){
        data.buf[i] = GetRandom();
        // printf("%d\n", data.buf[i]);
    }

    data.n = atoi(argv[1]) * 1024;
    
    //fwrite(&data, sizeof(unsigned int), SIZE, fp);
    for (i=0;i<SIZE-1; i++){
      fprintf(fp, "%d,",data.buf[i]);
    }
    fprintf(fp, "%d,\n",data.n);
    fclose(fp);
    
    return 0;
}
void CBaseParticleSystemFX::GetRandomColorInRange(DVector & vColor)
{
	DFLOAT fColorR = GetRandom(m_vColor1.x, m_vColor2.x);

	// Kludge the color for software...

	if (m_bSetSoftwareColor)
	{
		m_pClientDE->SetSoftwarePSColor(m_hObject, m_vColor1.x/255.0f, m_vColor1.y/255.0f, m_vColor1.z/255.0f);
	}

	if (m_vColorRange.x <= 0.0f)
	{
		VEC_COPY(vColor, m_vColor1);
	}
	else
	{
		vColor.x = fColorR;
		vColor.y = (m_vColorRange.y * fColorR) / m_vColorRange.x;
		vColor.z = (m_vColorRange.z * fColorR) / m_vColorRange.x;
	}

	return;
}
Exemple #11
0
static void SampleSobol(cSamples *samples, cBounds *b, creal vol)
{
  creal norm = vol*samples->weight;
  real *x = samples->x, *f = samples->f, *avg = samples->avg;
  ccount n = samples->n;
  count i, dim, comp;

  for( i = 0; i < n; ++i ) {
    GetRandom(x);
    for( dim = 0; dim < ndim_; ++x, ++dim )
      *x = b[dim].lower + *x*(b[dim].upper - b[dim].lower);
  }

  DoSample(n, ndim_, samples->x, f);

  ResCopy(avg, f);
  f += ncomp_;
  for( i = 1; i < n; ++i )
    for( comp = 0; comp < ncomp_; ++comp )
      avg[comp] += *f++;

  for( comp = 0; comp < ncomp_; ++comp )
    avg[comp] *= norm;
}
Exemple #12
0
void Bleed (edict_t *curse)
{
	int		take;
	edict_t *caster=curse->owner;

	if (curse->atype != BLEEDING)
		return;

	if (level.time < curse->wait)
		return;

	if (!G_ValidTarget(caster, curse->enemy, false))
	{
		// remove the curse if the target dies
		que_removeent(curse->enemy->curses, curse, true);
		return;
	}

	// 33-99% health taken over duration of curse
	take = (curse->enemy->max_health * (0.033 * curse->monsterinfo.level)) / curse->monsterinfo.selected_time;

	//gi.dprintf("target %s take %d health %d/%d level %d time %.1f\n", 
	//	curse->enemy->classname, take, curse->enemy->health, curse->enemy->max_health,
	//	curse->monsterinfo.level, curse->monsterinfo.selected_time);

	// damage limits
	if (take < 1)
		take = 1;
	if (take > 100)
		take = 100;

	T_Damage(curse->enemy, caster, caster, vec3_origin, vec3_origin, 
		vec3_origin, take, 0, DAMAGE_NO_ABILITIES, MOD_LIFE_DRAIN);

	curse->wait = level.time + (GetRandom(3, 10) * FRAMETIME);
}
Exemple #13
0
int main(int argc, const char** argv)
{
    const uint NUM_SHIPS = 50;
    const uint NUM_PLANETS = 500;
    const uint FIELD_DIMS = 500;
    GraphManager GraphManager;
    GraphManager.CreateGraph(NUM_PLANETS, { FIELD_DIMS, FIELD_DIMS });
    GraphManager.FormEdges();
    
    std::vector<Planet*> PlanetList;

    for (uint i = 0; i < GraphManager.NumNodes(); ++i)
    {
        Planet* p = new Planet(i, GraphManager.TakeNode());
        PlanetList.push_back(p);
    }
    std::vector<Ship> ShipList;
    for (uint i = 0; i < NUM_SHIPS; ++i)
    {
        ShipList.emplace_back(i, PlanetList[GetRandom(0, NUM_PLANETS)], [&] (GraphNode* Start, GraphNode* End)
        {
            auto GraphList = GraphManager.FindPath(Start, End);
            std::vector<Planet*> Result;
            for(auto Node : GraphList)
                for (Planet* Planet : PlanetList)
                    if (Planet->GetGraphNode() == Node)
                        Result.push_back(Planet);
            return Result;
        });
    }

    for (auto& Ship : ShipList)
        Ship.Tick(PlanetList);

    return 0;
}
// Returns true if the AI has a valid flame pot position for this link, false
// if it does not.
//
// Helper function for setting a flame pot position.  If the AI already has 
// a valid position, it will use it.  If the AI does not have a valid 
// position, a new position will be selected.
static bool SelectFlamePotPosition( CAI* pAI, AINavMeshLinkAbstract* pLink )
{
	// Sanity checks.

	if ( !pAI || !pLink )
	{
		return false;
	}

	//
	// Check to see if the AI already has a position.  If he does, use it.
	//

	CAIWMFact queryExistingFact;
	queryExistingFact.SetFactType( kFact_Knowledge );
	queryExistingFact.SetKnowledgeType( kKnowledge_FlamePotPosition );
	queryExistingFact.SetSourceObject( pAI->GetAIBlackBoard()->GetBBTargetObject() );
	queryExistingFact.SetTargetObject( pLink->GetHOBJECT() );
	CAIWMFact* pCurrentPosition = pAI->GetAIWorkingMemory()->FindWMFact( queryExistingFact );
	if ( NULL != pCurrentPosition )
	{
		// Ignore the point if the AI is already very close to it; this is 
		// likely an old position that was 'achieved'.

		LTVector vPosDelta2D = ( pAI->GetPosition() - pCurrentPosition->GetPos() );
		vPosDelta2D.y = 0.0f;
		float flDistanceSqr2D = vPosDelta2D.MagSqr();
		if ( flDistanceSqr2D >= g_flCirclingPositionAchievedDistSqr )
		{
			return true;
		}
	}

	CAINavMeshPoly* pPoly = g_pAINavMesh->GetNMPoly( pLink->GetNMPolyID() );
	if ( NULL == pPoly )
	{
		return false;
	}

	// Get the total length of the edge, so we can pick a number within the 
	// range [0, EdgeLength]

	int nEdges = pPoly->GetNumNMPolyEdges();
	float flEdgeLengthSum = 0.0f;
	for ( int i = 0; i < nEdges; ++i )
	{
		// Skip any edges which:
		// 1) Don't exist.
		// 2) Don't have polies on both sides.
		CAINavMeshEdge* pEdge = pPoly->GetNMPolyEdge( i );
		if ( !pEdge 
			|| kNMPoly_Invalid == pEdge->GetNMPolyIDA()
			|| kNMPoly_Invalid == pEdge->GetNMPolyIDB() )
		{
			continue;
		}

		flEdgeLengthSum += ( pEdge->GetNMEdge0() - pEdge->GetNMEdge1() ).Mag(); // TODO: Don't need to get the mag here.
	}

	// Fail if there are no valid positions.

	float flRandomDistanceAlongEdge = GetRandom( 0.0f, flEdgeLengthSum );
	if ( 0.0f == flRandomDistanceAlongEdge ) 
	{
		return false;
	}

	//
	// Select a position on the edge.
	//

	bool bFoundPosition = false;
	LTVector vSelectedPosition;
	float flRemainingDistance = flRandomDistanceAlongEdge;
	for ( int i = 0; i < nEdges; ++i )
	{
		// Skip any edges which:
		// 1) Don't exist.
		// 2) Don't have polies on both sides.
		CAINavMeshEdge* pEdge = pPoly->GetNMPolyEdge( i );
		if ( !pEdge 
			|| kNMPoly_Invalid == pEdge->GetNMPolyIDA()
			|| kNMPoly_Invalid == pEdge->GetNMPolyIDB() )
		{
			continue;
		}

		float flEdgeLength = ( pEdge->GetNMEdge0() - pEdge->GetNMEdge1() ).Mag(); // TODO: Don't need to get the mag here.
		if ( flRemainingDistance < flEdgeLength )
		{
			// Find the distance along the edge for the position.

			LTVector vEdgeDir = ( pEdge->GetNMEdge1() - pEdge->GetNMEdge0() ).GetUnit();
			vSelectedPosition = pEdge->GetNMEdge0() + ( vEdgeDir * flRemainingDistance );
		
			// Move the position 'out' of the link.  If we don't do this, the AI may 
			// end up standing in the flame pot link. If he does, the penalty 
			// for pathing through the link does not apply.

			LTVector vNormalOutOfLink;
			pEdge->GetNMEdgeN( pPoly->GetNMPolyID(), &vNormalOutOfLink );
			vNormalOutOfLink = -vNormalOutOfLink;

			vSelectedPosition += vNormalOutOfLink * 128.0f;

			bFoundPosition = true;
			break;
		}

		flRemainingDistance -= flEdgeLength;
	}

	if ( false == bFoundPosition )
	{
		return false;
	}

	//
	// Remember the position and objects involved so that the satisfying 
	// actions can use it, while validating that it is still valid.
	//

	CAIWMFact queryFact;
	queryFact.SetFactType( kFact_Knowledge );
	queryFact.SetKnowledgeType( kKnowledge_FlamePotPosition );
	CAIWMFact* pFact = pAI->GetAIWorkingMemory()->FindWMFact( queryExistingFact );
	if ( !pFact )
	{
		pFact = pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Knowledge );
		if ( pFact )
		{
			pFact->SetKnowledgeType( kKnowledge_FlamePotPosition );
		}
	}

	if ( pFact )
	{
		pFact->SetSourceObject( pAI->GetAIBlackBoard()->GetBBTargetObject() );
		pFact->SetTargetObject( pLink->GetHOBJECT() );
		pFact->SetPos( vSelectedPosition );
	}

	return true;
}
void CAIGoalCircleFlamePot::DeactivateGoal()
{
	super::DeactivateGoal();

	// If:
	// 1) The player is an enemy.
	// 2) There is another AI very close by
	// 3) That AI does not have a blitz task
	// ...this AI should blitz the player.  This is an anti-clumping measure.

	HOBJECT hTarget = m_pAI->GetAIBlackBoard()->GetBBTargetObject();

	bool bShouldBlitz = false;

	if ( m_pAI->HasTarget( kTarget_Character ) 
		&& IsPlayer( hTarget ) )
	{
		CAI::AIList::const_iterator itEachAI = CAI::GetAIList().begin();
		CAI::AIList::const_iterator itLastAI = CAI::GetAIList().end();
		for ( ; itEachAI != itLastAI; ++itEachAI )
		{
			CAI* pCurrentAI = *itEachAI;

			// Ignore NULL, self and dead AI.

			if ( NULL == pCurrentAI 
				|| pCurrentAI == m_pAI 
				|| IsDeadAI( pCurrentAI->GetHOBJECT() ) )
			{
				continue;
			}

			// Ignore AIs who are far away in 2D (false positives are okay).

			LTVector vDelta2D = ( pCurrentAI->GetPosition() - m_pAI->GetPosition() );
			vDelta2D.y = 0.0f;

			if ( vDelta2D.MagSqr() > g_flTooCloseToEnemySqr )
			{
				continue;
			}

			// Ignore AI who are already blitzing.

			CAIWMFact factQuery;
			factQuery.SetFactType( kFact_Task );
			factQuery.SetTaskType( kTask_BlitzCharacter );
			if ( pCurrentAI->GetAIWorkingMemory()->FindWMFact( factQuery ) )
			{
				continue;
			}

			// AI should blitz.

			bShouldBlitz = true;
			break;
		}
	}

	if ( bShouldBlitz || ( 0 == GetRandom( 0, 2 ) ) )
	{
		CAIWMFact factQuery;
		factQuery.SetFactType( kFact_Task );
		factQuery.SetTaskType( kTask_BlitzCharacter );
		CAIWMFact* pFact = m_pAI->GetAIWorkingMemory()->CreateWMFact( kFact_Task );
		if ( pFact )
		{
			pFact->SetTaskType( kTask_BlitzCharacter );
			pFact->SetTargetObject( hTarget );
			pFact->SetIndex( kContext_None );
			pFact->SetFactFlags( kFactFlag_Scripted, 1.f );
		}
	}
}
Exemple #16
0
DBOOL CShellCasingFX::Update()
{
	if (!m_hObject || !m_pClientDE) 
		return DFALSE;

	if (m_pClientDE->GetTime() > m_fExpireTime) 
		return DFALSE;

	if (m_bInVisible)
	{
		m_bInVisible = DFALSE;
		m_pClientDE->SetObjectFlags(m_hObject, FLAG_VISIBLE);
	}

	if (m_bResting) return DTRUE;

	DRotation rRot;

	// If velocity slows enough, and we're on the ground, just stop bouncing and just wait to expire.

	if (m_movingObj.m_PhysicsFlags & MO_RESTING)
	{
		m_bResting = DTRUE;

		// Stop the spinning...

		m_pClientDE->SetupEuler(&rRot, 0, m_fYaw, 0);
		m_pClientDE->SetObjectRotation(m_hObject, &rRot);	
/*		
		// Shell is at rest, we can add a check here to see if we really want
		// to keep it around depending on detail settings...

		HLOCALOBJ hObjs[1];
		DDWORD nNumFound, nBogus;
		m_pClientDE->FindObjectsInSphere(&m_movingObj.m_Pos, 64.0f, hObjs, 1, &nBogus, &nNumFound);

		// Remove thyself...
	
		if (nNumFound > 15) return DFALSE;
*/
	}
	else
	{
		if (m_fPitchVel != 0 || m_fYawVel != 0)
		{
			DFLOAT fDeltaTime = m_pClientDE->GetFrameTime();

			m_fPitch += m_fPitchVel * fDeltaTime;
			m_fYaw   += m_fYawVel * fDeltaTime;

			m_pClientDE->SetupEuler(&rRot, m_fPitch, m_fYaw, 0.0f);
			m_pClientDE->SetObjectRotation(m_hObject, &rRot);	
		}
	}


	DVector vNewPos;
	if (UpdateMovingObject(DNULL, &m_movingObj, &vNewPos))
	{
		ClientIntersectInfo info;
		SurfaceType eType = SURFTYPE_UNKNOWN;
		if (BounceMovingObject(DNULL, &m_movingObj, &vNewPos, &info, &eType))
		{
			if (m_nBounceCount > 0)
			{
				char sType[10];
				char sFile[MAX_CS_FILENAME_LEN];
				switch(eType)
				{
//					case SURFTYPE_FLESH:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Flesh"); break;
					case SURFTYPE_GLASS:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Glass"); break;
					case SURFTYPE_METAL:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Metal"); break;
					case SURFTYPE_PLASTIC:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Plastic"); break;
					case SURFTYPE_TERRAIN:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Terrain"); break;
					case SURFTYPE_LIQUID:	_mbscpy((unsigned char*)sType, (const unsigned char*)"Water"); break;
					case SURFTYPE_WOOD:		_mbscpy((unsigned char*)sType, (const unsigned char*)"Wood"); break;
					case SURFTYPE_STONE: 
					default:				_mbscpy((unsigned char*)sType, (const unsigned char*)"Stone"); break;
				}

				sprintf(sFile, "Sounds\\Weapons\\ShellDrops\\%s\\Shell%d.wav", sType, GetRandom(1, 2));

				PlaySoundFromPos(&vNewPos, sFile, 150.0f, SOUNDPRIORITY_MISC_LOW);
			}

			// Adjust the bouncing..

			m_fPitchVel = GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2);
			m_fYawVel	= GetRandom(-MATH_CIRCLE * 2, MATH_CIRCLE * 2);

			m_nBounceCount--;

			if (m_nBounceCount <= 0)
			{
				m_movingObj.m_PhysicsFlags |= MO_RESTING;
			}
		}

		VEC_COPY(m_movingObj.m_Pos, vNewPos);

		if (m_pClientDE->GetPointStatus(&vNewPos) == DE_OUTSIDE)
		{
 			return DFALSE;
		}

		m_pClientDE->SetObjectPos(m_hObject, &vNewPos);
	}

	return DTRUE;
}
Exemple #17
0
		void Player::FireWeapon() {
			SPADES_MARK_FUNCTION();
			
			Vector3 muzzle = GetEye();
			muzzle += GetFront() * 0.01f;
			
			// for hit-test debugging
			std::map<int, HitTestDebugger::PlayerHit> playerHits;
			std::vector<Vector3> bulletVectors;
			
			//Vector3 right = GetRight();
			//Vector3 up = GetUp();
			
			int pellets = weapon->GetPelletSize();
			float spread = weapon->GetSpread();
			GameMap *map = world->GetMap();
			
			// pyspades takes destroying more than one block as a
			// speed hack (shotgun does this)
			bool blockDestroyed = false;
			
			Vector3 dir2 = GetFront();
			for(int i =0 ; i < pellets; i++){
				
				// AoS 0.75's way (dir2 shouldn't be normalized!)
				dir2.x += (GetRandom() - GetRandom()) * spread;
				dir2.y += (GetRandom() - GetRandom()) * spread;
				dir2.z += (GetRandom() - GetRandom()) * spread;
				Vector3 dir = dir2.Normalize();
				
				bulletVectors.push_back(dir);
				
				// first do map raycast
				GameMap::RayCastResult mapResult;
				mapResult = map->CastRay2(muzzle,
										  dir,
										  500);
				
				Player *hitPlayer = NULL;
				float hitPlayerDistance = 0.f;
				HitBodyPart hitPart = HitBodyPart::None;
				
				for(int i = 0; i < world->GetNumPlayerSlots(); i++){
					Player *other = world->GetPlayer(i);
					if(other == this || other == NULL)
						continue;
					if(other == this || !other->IsAlive() ||
					   other->GetTeamId() >= 2)
						continue;
					// quickly reject players unlikely to be hit
					if(!other->RayCastApprox(muzzle, dir))
						continue;
					
					HitBoxes hb = other->GetHitBoxes();
					Vector3 hitPos;
					
					if(hb.head.RayCast(muzzle, dir, &hitPos)) {
						float dist = (hitPos - muzzle).GetLength();
						if(hitPlayer == NULL ||
						   dist < hitPlayerDistance){
							hitPlayer = other;
							hitPlayerDistance = dist;
							hitPart = HitBodyPart::Head;
						}
					}
					if(hb.torso.RayCast(muzzle, dir, &hitPos)) {
						float dist = (hitPos - muzzle).GetLength();
						if(hitPlayer == NULL ||
						   dist < hitPlayerDistance){
							hitPlayer = other;
							hitPlayerDistance = dist;
							hitPart = HitBodyPart::Torso;
						}
					}
					for(int j = 0; j < 3 ;j++){
						if(hb.limbs[j].RayCast(muzzle, dir, &hitPos)) {
							float dist = (hitPos - muzzle).GetLength();
							if(hitPlayer == NULL ||
							   dist < hitPlayerDistance){
								hitPlayer = other;
								hitPlayerDistance = dist;
								switch(j) {
									case 0: hitPart = HitBodyPart::Limb1; break;
									case 1: hitPart = HitBodyPart::Limb2; break;
									case 2: hitPart = HitBodyPart::Arms;  break;
								}
							}
						}
					}
				}
				
				Vector3 finalHitPos;
				finalHitPos = muzzle + dir * 128.f;
				
				if(hitPlayer == nullptr && !mapResult.hit) {
					// might hit water surface.
					
				}
				
				if(mapResult.hit && (mapResult.hitPos - muzzle).GetLength() < 128.f &&
				   (hitPlayer == NULL || (mapResult.hitPos - muzzle).GetLength() < hitPlayerDistance)){
					IntVector3 outBlockCoord = mapResult.hitBlock;
					// TODO: set correct ray distance
					// FIXME: why ray casting twice?
					
					finalHitPos = mapResult.hitPos;
					
					if(outBlockCoord.x >= 0 && outBlockCoord.y >= 0 && outBlockCoord.z >= 0 &&
					   outBlockCoord.x < map->Width() && outBlockCoord.y < map->Height() &&
					   outBlockCoord.z < map->Depth()){
						if(outBlockCoord.z == 63) {
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}else if(outBlockCoord.z == 62) {
							// blocks at this level cannot be damaged
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}else{
							int x = outBlockCoord.x;
							int y = outBlockCoord.y;
							int z = outBlockCoord.z;
							SPAssert(map->IsSolid(x, y, z));
							
							Vector3 blockF = {x + .5f, y + .5f, z + .5f};
							float distance = (blockF - muzzle).GetLength();
							
							uint32_t color = map->GetColor(x, y, z);
							int health = color >> 24;
							health -= weapon->GetDamage(HitTypeBlock, distance);
							if(health <= 0 && !blockDestroyed){
								health = 0;
								blockDestroyed = true;
								//send destroy cmd
								if(world->GetListener() &&
								   world->GetLocalPlayer() == this)
									world->GetListener()->LocalPlayerBlockAction
									(outBlockCoord, BlockActionTool);
								
							}
							color = (color & 0xffffff) | ((uint32_t)health << 24);
							if(map->IsSolid(x, y, z))
								map->Set(x, y, z, true, color);
							
							if(world->GetListener())
								world->GetListener()->BulletHitBlock(mapResult.hitPos,
																	 mapResult.hitBlock,
																	 mapResult.normal);
						}
					}
			    }else if(hitPlayer != NULL){
Exemple #18
0
void Color::SetRandom(){
  SetValor(GetRandom(0,6));
}
Exemple #19
0
void p_medic_reanimate (edict_t *ent, edict_t *target)
{
	int		skill_level;
	vec3_t	bmin, bmax;
	edict_t *e;

	skill_level = floattoint((1.0+MEDIC_RESURRECT_BONUS)*ent->myskills.abilities[MEDIC].current_level);

	if (!strcmp(target->classname, "drone") 
		&& (ent->num_monsters + target->monsterinfo.control_cost <= MAX_MONSTERS))
	{
		target->monsterinfo.level = skill_level;
		M_SetBoundingBox(target->mtype, bmin, bmax);

		if (G_IsValidLocation(target, target->s.origin, bmin, bmax) && M_Initialize(ent, target))
		{
			// restore this drone
			target->monsterinfo.slots_freed = false; // reset freed flag
			target->health = 0.33*target->max_health;
			target->monsterinfo.power_armor_power = 0.33*target->monsterinfo.max_armor;
			target->monsterinfo.resurrected_time = level.time + 2.0;
			target->activator = ent; // transfer ownership!
			target->nextthink = level.time + MEDIC_RESURRECT_DELAY;
			gi.linkentity(target);
			target->monsterinfo.stand(target);

			ent->num_monsters += target->monsterinfo.control_cost;
			safe_cprintf(ent, PRINT_HIGH, "Resurrected a %s. (%d/%d)\n", 
				target->classname, ent->num_monsters, MAX_MONSTERS);
		}
	}
	else if ((!strcmp(target->classname, "bodyque") || !strcmp(target->classname, "player"))
		&& (ent->num_monsters + 1 <= MAX_MONSTERS))
	{
		int		random=GetRandom(1, 3);
		vec3_t	start;

		e = G_Spawn();

		VectorCopy(target->s.origin, start);

		// kill the corpse
		T_Damage(target, target, target, vec3_origin, target->s.origin, 
			vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, 0);

		//4.2 random soldier type with different weapons
		if (random == 1)
		{
			// blaster
			e->mtype = M_SOLDIER;
			e->s.skinnum = 0;
		}
		else if (random == 2)
		{
			// rocket
			e->mtype = M_SOLDIERLT;
			e->s.skinnum = 4;
		}
		else
		{
			// shotgun
			e->mtype = M_SOLDIERSS;
			e->s.skinnum = 2;
		}

		e->activator = ent;
		e->monsterinfo.level = skill_level;
		M_Initialize(ent, e);
		e->health = 0.2*e->max_health;
		e->monsterinfo.power_armor_power = 0.2*e->monsterinfo.max_armor;
		e->s.skinnum |= 1; // injured skin

		e->monsterinfo.stand(e);
		
		if (!G_IsValidLocation(target, start, e->mins, e->maxs))
		{
			start[2] += 24;
			if (!G_IsValidLocation(target, start, e->mins, e->maxs))
			{
				G_FreeEdict(e);
				return;
			}
		}

		VectorCopy(start, e->s.origin);
		gi.linkentity(e);
		e->nextthink = level.time + MEDIC_RESURRECT_DELAY;

		ent->num_monsters += e->monsterinfo.control_cost;

		safe_cprintf(ent, PRINT_HIGH, "Resurrected a soldier. (%d/%d)\n", 
			ent->num_monsters, MAX_MONSTERS);
	}
	else if (!strcmp(target->classname, "spiker") && ent->num_spikers + 1 <= SPIKER_MAX_COUNT)
	{
		e = CreateSpiker(ent, skill_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_spikers--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->health = 0.33 * e->max_health;
		e->s.frame = 4;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);
	}
	else if (!strcmp(target->classname, "obstacle") && ent->num_obstacle + 1 <= OBSTACLE_MAX_COUNT)
	{
		e = CreateObstacle(ent, skill_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_obstacle--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->health = 0.33 * e->max_health;
		e->s.frame = 6;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);
	}
	else if (!strcmp(target->classname, "gasser") && ent->num_gasser + 1 <= GASSER_MAX_COUNT)
	{
		e = CreateGasser(ent, skill_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_gasser--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->health = 0.33 * e->max_health;
		e->s.frame = 0;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);
	}
		
}
void ProcDropItemAfterBattle(CNPC* df, CPC* opc, CPC* tpc, int level)
{
	if(df->m_pZone->IsComboZone())
	{
		DropComboGiftMob(df, opc, tpc, level);
		return ;
	}

#ifdef SYSTEM_TREASURE_MAP
	if( df->m_idNum == TREASURE_BOX_NPC_INDEX ) // npc 일경우 보물 상자만 드랍 한다.
	{
		DropTreasureBoxNpc(df, opc, tpc, level);
		return;
	}

	// 보물 지도는 필드에서만 드랍된다.
	if( df->m_pZone->CheckTreasureDropFlag() && df->m_pZone->IsFieldZone() )
	{
		DropTreasureMap(df, opc, tpc, level);
	}
#endif

	// 아이템 드롭율 증폭제 검사
	bool hcSepDrop = false;
	bool hcDropPlus_S360 = false;
	bool hcPlatinumDrop = false;

	if (opc && tpc == opc)
	{
		if (opc->m_assist.m_avAddition.hcSepDrop)
		{
			opc->m_assist.CureByItemIndex(884);	// 아이템
			hcSepDrop = true;
			CNetMsg::SP rmsg(new CNetMsg);
			EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP);
			SEND_Q(rmsg, opc->m_desc);
		}

		if (opc->m_assist.m_avAddition.hcSepDrop_Cash)
		{
			opc->m_assist.CureByItemIndex(6096);	// 아이템
			hcSepDrop = true;
			CNetMsg::SP rmsg(new CNetMsg);
			EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_DROP);
			SEND_Q(rmsg, opc->m_desc);
		}

		// 추천서버포션 드롭율 상승
		else if (opc->m_assist.m_avAddition.hcDropPlus_S360)
		{
			opc->m_assist.CureBySkillIndex(360);
			hcDropPlus_S360 = true;
		}
		else if(opc->m_assist.m_avAddition.hcPlatinumDrop)
		{
			opc->m_assist.CureByItemIndex(2855);	// 아이템
			hcPlatinumDrop = true;
		}
	} // 아이템 드롭율 증폭제 검사

	// 아이템 드롭
	int loopcount;
	bool IsNotDropInCube = true;
#ifdef EXTREME_CUBE
	if(df->m_bCubeRegen)
		IsNotDropInCube = false;
#endif // EXTREME_CUBE]

	int itemDropLoop = MAX_NPC_DROPITEM_LOOP;
#ifdef EVENT_WORLDCUP_2010
	if( df->m_proto->m_index == 1105 )
		itemDropLoop = 1;
#endif // #ifdef EVENT_WORLDCUP_2010

	for (loopcount = 0; loopcount < itemDropLoop; loopcount++)
	{
		// 5레벨보다 크면 아이템 드롭 없음
		// 1. 드롭할 수 있는 수 범위에서 아이템 선정
		// 2. 그 아이팀의 드롭확률로 드롭여부 결정
		// 3. 드롭
#ifdef EVENT_WORLDCUP_2010 // 트라이앵글 볼(1105) 일경우 무조건 아이템을 드랍 한다
		if( ( df->m_proto->m_itemCount > 0 &&  ((level != -1 && level - df->m_level <= 5) ||  !IsNotDropInCube) )
			|| df->m_proto->m_index == 1105)
#else
		if (df->m_proto->m_itemCount > 0 &&  ((level != -1 && level - df->m_level <= 5) ||  !IsNotDropInCube) )
#endif
		{
			CItem* dropItem = NULL;
			int tableindex;
#ifdef EVENT_WORLDCUP_2010
			if( df->m_proto->m_index == 1105 )
			{
				// npc툴 드랍 테이블1,2번에 각각 축국공, 황금 축구공이  100%g확률로 들어가 있어야 한다.
				tableindex = GetRandom(1, 10000); // 0. 95%확률로 축구공. 1. 5% 확률 황금 축구공 2. 꽝
				if( tableindex <= 9000 )
					tableindex = 0;
				else if( tableindex <= 9500)
					tableindex = 1;
				else
					tableindex = 2;
			}
			else
#endif
				tableindex = GetRandom(0, MAX_NPC_DROPITEM - 1);
			int dropprob = df->m_proto->m_itemPercent[tableindex];

			dropprob = dropprob * gserver->m_itemDropProb / 100;

			if (tpc)
			{
				// 자두
				if (tpc->m_assist.m_avAddition.hcDropPlus_838)
					dropprob *= 2;

				// 행운의스크롤, 5080강운의 스크롤과 변수를 같이 사용한다.
				if (tpc->m_assist.m_avAddition.hcScrollDrop)
					dropprob *= 2;

				if (tpc->m_assist.m_avAddition.hcScrollDrop_5081)
					dropprob *= 4;

				// 행운 주문서
				if (tpc->m_assist.m_avAddition.hcDropPlus_2141)
				{
					if (GetRandom(1, 10000) <= 2000 ) // 20 %
					{
						dropprob *= 2;
					}
				}

				// 플래티늄 행운의 스크롤
				if(tpc->m_assist.m_avAddition.hcPlatinumScroll)
				{
					dropprob *= 4;
				}
			}

			// BS 수정 : 아이템 드롭 이벤트
			dropprob = dropprob * gserver->m_nItemDropEventRate / 100;

			// 드롭율 상승 %단위 누적
			if (opc && tpc == opc && opc->m_assist.m_avAddition.hcDropPlusPer100 > 0)
				dropprob += dropprob * opc->m_assist.m_avAddition.hcDropPlusPer100 / 100;

#ifdef DOUBLE_ITEM_DROP
			if ( gserver->m_bDoubleItemEvent )
				dropprob += dropprob * gserver->m_bDoubleItemPercent / 100;
#endif // DOUBLE_ITEM_DROP

			// 9월 이벤트 드롭율 10배
			if (hcSepDrop)
				dropprob = dropprob * 10;

			// 추천서버포션 드롭율 상승
			else if (hcDropPlus_S360)
				dropprob = dropprob * 10;

			else if (hcPlatinumDrop)
				dropprob = dropprob * 20;

			if( opc && opc->m_assist.m_avAddition.hcRandomDropUp > 0  && GetRandom(0,100) <= opc->m_assist.m_avAddition.hcRandomDropUp )
			{
				dropprob = dropprob * 10;
				CNetMsg::SP rmsg(new CNetMsg);
				EffectEtcMsg(rmsg, opc, MSG_EFFECT_ETC_RANDOM_DROP);
				opc->m_pArea->SendToCell(rmsg, opc, true);
			}

			if( tpc )
			{
				if( gserver->isActiveEvent( A_EVENT_XMAS) )
				{
					if ( tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007 > 0)
						dropprob += df->m_proto->m_itemPercent[tableindex] * tpc->m_assist.m_avAddition.hcDropPlus_Xmas2007;
				}
			}

#ifdef IMP_SPEED_SERVER
			// Zone Drop 률 적용
			if( gserver->m_bSpeedServer && tpc && tpc->m_pZone )
			{
				dropprob = dropprob * tpc->m_pZone->GetZoneDrop() / 100;
			}
#endif //IMP_SPEED_SERVER

			if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob)
			{
				if (df->m_proto->m_item[tableindex] == 84)
				{
					dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, df->m_level, 1);
				}
#if defined (LC_USA) || defined(LC_BILA)
				// 대만과 말레이시아는 중소형 체력약이 소형으로 떨어진다
				else if( df->m_proto->m_item[tableindex] == 44
						 || df->m_proto->m_item[tableindex] == 45 )
				{
					dropItem = df->m_pArea->DropItem(43, df, 0, 0, 1);
				}
				// 대만과 말레이시아는 중형 마나 회복 물약이 드롭되지 않는다.
				else if ( df->m_proto->m_item[tableindex] == 485 )
				{
					dropItem = NULL;
				}
#endif // #if defined (LC_USA) || defined(LC_BILA)
#if defined (LC_USA) || defined(LC_BILA)
				// 대형 힐링포션 제작서, 대형 마나, 중형 마나 메뉴얼 드롭 금지
				else if ( df->m_proto->m_item[tableindex] == 1066
						  || df->m_proto->m_item[tableindex] == 1067
						  || df->m_proto->m_item[tableindex] == 1068
						  || df->m_proto->m_item[tableindex] == 489)
				{
					dropItem = NULL;
				}
#endif // #if defined (LC_USA) || defined (LC_BILA)
				else
				{
					// 61레벨 무기류 및 65레벨 방어구 드롭 금지 제작서 드롭 금지
					switch (df->m_proto->m_item[tableindex])
					{
					case -1:	// 지우지 말것
						dropItem = NULL;
						break;

					default:
						{
							bool bAvailableDrop = true;
							if (bAvailableDrop)
								dropItem = df->m_pArea->DropItem(df->m_proto->m_item[tableindex], df, 0, 0, 1, true);
							else
								dropItem = NULL;
						}
						break;
					} // switch (df->m_proto->m_item[tableindex])
				}
			} // if (df->m_proto->m_item[tableindex] != -1 && GetRandom(1, 10000) <= dropprob)

			if (dropItem)
			{
// 050303 : bs : 몬스터에게서 plus 붙은 아이템 만들기
				if (df->m_proto->m_minplus >= 0 && df->m_proto->m_maxplus >= df->m_proto->m_minplus && df->m_proto->m_probplus > 0 && dropItem->CanUpgrade())
				{
					if (GetRandom(1, 10000) <= df->m_proto->m_probplus)
					{
						dropItem->setPlus(GetRandom(df->m_proto->m_minplus, df->m_proto->m_maxplus));
					}
				}

				// Drop Msg 보내기
				// 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려)
				if (tpc)
					dropItem->m_preferenceIndex = tpc->m_index;
				else
					dropItem->m_preferenceIndex = -1;

				{
					CNetMsg::SP rmsg(new CNetMsg);
					ItemDropMsg(rmsg, df, dropItem);
					df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ);
				}

				if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS))
				{
					GAMELOG << init("MOB DROP ITEM")
							<< "NPC INDEX" << delim
							<< df->m_proto->m_index << delim
							<< "NPC NAME" << delim
							<< df->m_name << delim
							<< "ITEM" << delim
							<< itemlog(dropItem)
							<< end;
				}
			}
		}
	} // // 아이템 드롭

	// opc 공격 캐릭터, tpc 우선권 캐릭터
	int job = -1;

	if(tpc)
		job = (int)tpc->m_job;
	else if(opc)
		job = (int)opc->m_job;

	if(job >= 0 && job < JOBCOUNT)
	{
		if(level != -1 && level - df->m_level <= 5)
		{
			if(df->m_proto->m_jobdropitem[job] > 0 && df->m_proto->m_jobdropitemprob[job] > 0)
			{
				int dropprob = df->m_proto->m_jobdropitemprob[job];
				if(GetRandom(1, 10000) <= dropprob)
				{
					CItem* dropItem = NULL;
					dropItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_jobdropitem[job], -1, 0, 0, 1);
					if(dropItem)
					{
						df->m_pArea->DropItem(dropItem, df);
						CNetMsg::SP rmsg(new CNetMsg);
						ItemDropMsg(rmsg, df, dropItem);
						df->m_pArea->SendToCell(rmsg, df, true);
						GAMELOG << init("MOB DROP ITEM")
								<< "NPC INDEX" << delim
								<< df->m_proto->m_index << delim
								<< "NPC NAME" << delim
								<< df->m_name << delim
								<< "ITEM" << delim
								<< itemlog(dropItem)
								<< end;
					}
				}
			}
		}
	}

	// 이 아이템은 레벨제한 없이 무조건 떨어트린다.
	int loopi = 0;
	for(loopi = 0; loopi < MAX_NPC_DROPITEM; loopi++)
	{
		if(df->m_proto->m_dropallitem[loopi] < 1)
			continue ;

		int dropprob = df->m_proto->m_dropallitemprob[loopi];
		if(GetRandom(1, 10000) <= dropprob)
		{
			CItem* pItem = NULL;

			pItem = gserver->m_itemProtoList.CreateItem(df->m_proto->m_dropallitem[loopi], -1, 0, 0, 1);
			if(pItem)
			{
				if (tpc)
					pItem->m_preferenceIndex = tpc->m_index;
				else
					pItem->m_preferenceIndex = -1;

				df->m_pArea->DropItem(pItem, df);
				CNetMsg::SP rmsg(new CNetMsg);
				ItemDropMsg(rmsg, df, pItem);
				df->m_pArea->SendToCell(rmsg, df, true);
				GAMELOG << init("MOB DROP ALL ITEM")
						<< "NPC INDEX" << delim
						<< df->m_proto->m_index << delim
						<< "NPC NAME" << delim
						<< df->m_name << delim
						<< "ITEM" << delim
						<< itemlog(pItem)
						<< end;
			}
		}
	}
	// 보석 드롭
	for (loopcount = 0; loopcount < MAX_NPC_DROPITEM_LOOP; loopcount++)
	{
		// 5레벨보다 크면 아이템 드롭 없음
		// 1. 드롭할 수 있는 수 범위에서 아이템 선정
		// 2. 그 아이팀의 드롭확률로 드롭여부 결정
		// 3. 드롭
		if (df->m_proto->m_jewelCount > 0 &&  ((level != -1 && level - df->m_level <= 5) ||  !IsNotDropInCube)  )
		{
			CItem* dropItem = NULL;
			int tableindex = GetRandom(0, MAX_NPC_DROPJEWEL - 1);
			int dropprob = df->m_proto->m_jewelPercent[tableindex];

			if (df->m_proto->m_jewel[tableindex] != -1 && GetRandom(1, 10000) <= dropprob)
			{
				switch (df->m_proto->m_jewel[tableindex])
				{
				case -1:	// 지우지 말것
					dropItem = NULL;
					break;

				default:
					{
						dropItem = df->m_pArea->DropItem(df->m_proto->m_jewel[tableindex], df, 0, 0, 1, true);
					}
					break;
				}
			}

			if (dropItem)
			{
				// Drop Msg 보내기
				// 아이템 우선권 셋팅 (같은 데미지 고려, 선공 고려)
				if (tpc)
					dropItem->m_preferenceIndex = tpc->m_index;
				else
					dropItem->m_preferenceIndex = -1;

				{
					CNetMsg::SP rmsg(new CNetMsg);
					ItemDropMsg(rmsg, df, dropItem);
					df->m_pArea->SendToCell(rmsg, GET_YLAYER(dropItem), dropItem->m_cellX, dropItem->m_cellZ);
				}

				GAMELOG << init("JEWEL ITEM")
						<< "NPC INDEX" << delim
						<< df->m_proto->m_index << delim
						<< "NPC NAME" << delim
						<< df->m_name << delim
						<< "ITEM" << delim
						<< itemlog(dropItem)
						<< end;
			}
		}
	} // 보석 드롭
	// typedef void (*NPC_DROP_FUNCTION) (CNPC* npc, CPC* pc, CPC* tpc, int level);
	// pc, tpc는 NULL이 될 수 있다
	NPC_DROP_FUNCTION fnNPCDrop[] =
	{
		DropBloodGem,						// 블러드젬 드롭 : 대만 천하대란
		DropLuckySpecialStone,				// 행운의 제련석 드롭 : 대만 천하대란
		DropSpecialRefineStone,				// 고제 드롭
		DropPersonalDungeon2Ticket,			// 퍼스널던전 2 입장권 드롭
		DropBoosterItem,					// 부스터

		DropPersonalDungeon3Ticket,			// 퍼스널던전 3 입장권 드롭
		DropPersonalDungeon4Ticket,			// 퍼스널던전 4 입장권 드롭

		DropPetEgg,							// 애완동물 알 드롭

		DropNewMoonStoneItem,

#ifdef EVENT_VALENTINE
		DropValentineItem,					// 발렌타인
#endif

#ifdef EVENT_WHITEDAY
		DropWhiteDayItem,					// 화이트데이
#endif

#ifdef DROP_MAKE_DOCUMENT
		DropMakeDocument,					// 제작문서 드롭
#endif // DROP_MAKE_DOCUMENT

		DropRecommendItem,					// 추천 서버 전용 인스턴스 포션 아이템

		DropGoldenBallItem,					// 골든볼 이벤트

		RegenBlessWarrior,					// 전사의 축복

		DropHalloween2006Item,				// 2006 할로윈 이벤트

		DropRaidMonsterItem,

		DropMobScrollSpecialStone,

		DropEventGomdori2007,

		DropEventIndependenceDay2007USA,

		DropEventAprilFoolEvent,

#ifdef EVENT_DROPITEM
		DropEventNpcDropItem,
#endif // EVENT_DROPITEM

		DropAPetLifeBook,

		DropPhoenix_MembersTicket,

		DropTriggerItem,

#ifdef LACARETTE_SYSTEM
		DropLacaRette,
#endif
		DropHolyWater,
		DropWorldCupEvent,
		DropHalloween2014Event,
		DropArtifactItem,

#ifdef DEV_EVENT_AUTO
		DropEventItem,
#endif // DEV_EVENT_AUTO
	}; // 드롭 함수 테이블

	// 방어코드 : tpc가 있는데 m_pZone이나 m_pArea가 없으면 NULL로 바꾼다
	if (tpc && (tpc->m_pZone == NULL || tpc->m_pArea == NULL))
		tpc = NULL;

	unsigned int fnDropLoop;
	for (fnDropLoop = 0; fnDropLoop < sizeof(fnNPCDrop) / sizeof(NPC_DROP_FUNCTION); fnDropLoop++)
		(fnNPCDrop[fnDropLoop])(df, opc, tpc, level);

	gserver->doEventDropItem(df, opc, tpc);

	// 돈 떨어뜨릴 확률 : default 80 %
	// BS 수정 : 낮은 레벨 몬스터 잡을때 패널티만 존재
	// 잠수함 : 돈 드롭확률
	int moneyDropProb = MONEY_DROP_PROB * gserver->m_moneyDropProb / 100;
	if (level != -1 && df->m_level - level < 0)
		moneyDropProb += (df->m_level - level) * 500;

	bool hcSepNas = false;
	if (opc && tpc == opc)
	{
		if (opc->m_assist.m_avAddition.hcSepNas)
		{
			opc->m_assist.CureByItemIndex(885);	// 나스
			hcSepNas = true;
			CNetMsg::SP rmsg(new CNetMsg);
			EventErrorMsg(rmsg, MSG_EVENT_ERROR_SEPTEMBER_NAS);
			SEND_Q(rmsg, opc->m_desc);
		}
	}

	// 돈 드롭
	//CItem* money = NULL;
	if (GetRandom(1, 10000) <= moneyDropProb)	// 80%
	{
		// 돈 액수 : +- 50%
		if(!df)
		{
			//잘못된 위치에서 몬스터를 잡았을 경우
			GAMELOG << "NOT FOUND TARGET....."
					<< df->m_idNum
					<< end;
			return ;
		}
		GoldType_t count = df->m_proto->m_price * GetRandom(50, 150) / 100;

#ifdef LC_RUS
		// 러시아는 망각의 신전을 제외한 지역에서 65 레벨 이상의 몬스터가 떨구는 나스는 40% 로 줄인다.
		if (df->m_pZone && df->m_pZone->m_index != ZONE_DUNGEON4 && df->m_level >= 65)
			count = count / 5 * 2;
#endif // LC_RUS

		// 더블이벤트
		if (gserver->m_bDoubleEvent)
		{
#ifdef NEW_DOUBLE_GM_ZONE
			if( gserver->m_bDoubleEventZone == -1 || gserver->m_bDoubleEventZone == df->m_pZone->m_index )
#endif // NEW_DOUBLE_GM_ZONE
				count = count * gserver->m_bDoubleNasPercent / 100 ;
		}

		// 9월 이벤트 나스 10배
		if (hcSepNas)
			count = count * 10;

		// 행운 주문서
		if (tpc && tpc->m_assist.m_avAddition.hcDropPlus_2141)
		{
			if (GetRandom(1, 10000) <= 8000 ) // 80 %
			{
				count *= 2;
			}
		}

//#endif // CAHNCE_EVENT

		if( opc && opc->m_pZone->m_index == ZONE_DRATAN_CASTLE_DUNGEON )
		{
			CDratanCastle * pCastle = CDratanCastle::CreateInstance();
			if( opc->m_guildInfo && opc->m_guildInfo->guild()->index() == pCastle->GetOwnerGuildIndex()  )
			{
				// 세금 없음
			}
			else
			{
				GoldType_t tax=0;
				tax = count * pCastle->m_dvd.GetHuntRate() / 100;
				count = count - tax;
				gserver->AddTaxItemDratan( tax );
			}
		}

		if( tpc == NULL )
		{
			GAMELOG << "NOT FOUND TARGET....." << end;
			return;
		}

		//파티이면서 타입이 균등일때
		if (tpc->IsParty() && (tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_RANDOM || tpc->m_party->GetPartyType(MSG_DIVITYPE_MONEY) == MSG_PARTY_TYPE_BATTLE) )
		{
			DivisionPartyMoney(tpc, count);
		}
		//원정대이면서 타입이 균등일때
		else if ( tpc->IsExped() && (tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_RANDOM || tpc->m_Exped->GetExpedType(MSG_DIVITYPE_MONEY) == MSG_EXPED_TYPE_BATTLE) )
		{
			DivisionExpedMoney(tpc, count);
		}
		//이도 저도 아닐때 (개인 플레이할때)
		else
		{
			int bonus = 0;

			if(tpc->m_avPassiveAddition.money_nas > 0)
			{
				bonus += tpc->m_avPassiveAddition.money_nas;	
			}
			if(tpc->m_avPassiveRate.money_nas > 0)
			{
				bonus = count * (tpc->m_avPassiveRate.money_nas - 100) / SKILL_RATE_UNIT;
			}

			count = count + count * tpc->m_artiGold / 100;
			
			tpc->m_inventory.increaseMoney(count, bonus);
		}

		if (df->m_proto->CheckFlag(NPC_BOSS | NPC_MBOSS))
		{
			GAMELOG << init("MOB DROP MONEY")
					<< "NPC INDEX" << delim
					<< df->m_proto->m_index << delim
					<< "NPC NAME" << delim
					<< df->m_name << delim
					<< "MONEY(NAS)" << delim
					<< count
					<< end;
		}
	}
}
Exemple #21
0
LTBOOL CLineSystemFX::Update()
{
    if (!m_hObject || !m_pClientDE || m_bWantRemove) return LTFALSE;

    LTFLOAT fTime = m_pClientDE->GetTime();

	// Hide/show the line system if necessary...

	if (m_hServerObject)
	{
        uint32 dwUserFlags;
		g_pCommonLT->GetObjectFlags(m_hServerObject, OFT_User, dwUserFlags);

		if (!(dwUserFlags & USRFLG_VISIBLE))
		{
			g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, 0, FLAG_VISIBLE);
			m_fLastTime = fTime;
            return LTTRUE;
		}
		else
		{
			g_pCommonLT->SetObjectFlags(m_hObject, OFT_Flags, FLAG_VISIBLE, FLAG_VISIBLE);
		}
	}

	// Debugging aid...

	if (s_cvarTweak.GetFloat() > 0)
	{
		TweakSystem();
	}


	if (m_bFirstUpdate)
	{
		m_fLastTime = fTime;
        m_bFirstUpdate = LTFALSE;
	}
	else
	{
		UpdateSystem();
	}

	// Make sure it is time to update...

	if (fTime < m_fLastTime + m_fNextUpdate)
	{
        return LTTRUE;
	}


	// Ok, how many to add this frame....

	float fTimeDelta = fTime - m_fLastTime;

	// Make sure delta time is no less than 15 frames/sec if we're
	// continuously adding lines...

	if (m_bContinuous)
	{
		fTimeDelta = fTimeDelta > 0.0666f ? 0.0666f : fTimeDelta;
	}

	int nToAdd = (int) floor(m_cs.fLinesPerSecond * fTimeDelta);
    nToAdd = LTMIN(nToAdd, (int)(MAX_LINES_PER_SECOND * fTimeDelta));


	// Add new lines...

	AddLines(nToAdd);


	// Determine when next update should occur...

	if (m_cs.fBurstWait > 0.001f)
	{
		m_fNextUpdate = m_cs.fBurstWait * GetRandom(m_cs.fBurstWaitMin, m_cs.fBurstWaitMax);
	}
	else
	{
		m_fNextUpdate = 0.001f;
	}

	m_fLastTime = fTime;

    return LTTRUE;
}
// 믈리 어택
void do_pd_Attack(CPC* pc, CNetMsg::SP& msg)
{
	CDratanCastle * pCastle = CDratanCastle::CreateInstance();
	pCastle->CheckRespond(pc);

	RequestClient::doPDAttack* packet = reinterpret_cast<RequestClient::doPDAttack*>(msg->m_buf);

	if (packet->multicount > 20)
	{
		LOG_ERROR("HACKING : invalid multi count[%d]. charIndex[%d]", packet->multicount, pc->m_index);
		pc->m_desc->Close("invalid multi count");
		return;
	}

	// multi target의 중복 검사
	if (packet->multicount > 1)
	{
		std::set<int> tset;
		for (int i = 0; i < packet->multicount; ++i)
		{
			if (tset.insert(packet->list[i].index).second == false)
			{
				LOG_ERROR("HACKING : duplicate multi target[%d]. charIndex[%d]", packet->list[i].index, pc->m_index);
				pc->m_desc->Close("duplicate multi target");
				return;
			}
		}
	}

	// 대상 검색 : 인접 셀에서만
	CArea* area = pc->m_pArea;
	if (area == NULL)
	{
		LOG_ERROR("HACKING : not found area. charIndex[%d]", pc->m_index);
		pc->m_desc->Close("not found area");
		return;
	}

	CCharacter* tch = area->FindCharInCell(pc, packet->tIndex, (MSG_CHAR_TYPE)packet->tCharType);
	if (tch == NULL)
		return;

	int preIndex = -1;
	for (int i = 0; i < packet->multicount; ++i)
	{
		if(preIndex == packet->list[i].index)
		{
			// 가까운 마을로
			int nearZone;
			int nearZonePos;
			CZone* pZone = gserver->FindNearestZone(pc->m_pZone->m_index, GET_X(pc), GET_Z(pc), &nearZone, &nearZonePos);
			if (pZone == NULL)
				return;

			GoZone(pc, nearZone,
				   pZone->m_zonePos[nearZonePos][0],															// ylayer
				   GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f,		// x
				   GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f);		// z

			return;
		}

		preIndex = packet->list[i].index;

		CCharacter* ch = area->FindCharInCell(pc, packet->list[i].index, (MSG_CHAR_TYPE) MSG_CHAR_NPC);

		if(!ch) continue;

		if( !IS_NPC(ch) )
		{
			CPC* bugPC = NULL;
			if( IS_ELEMENTAL(ch) )
			{
				CElemental *ele = TO_ELEMENTAL(ch);
				bugPC = ele->GetOwner();
			}
			if( IS_PET(ch) )
			{
				CPet* pet = TO_PET(ch);
				bugPC = pet->GetOwner();
			}

			if( IS_PC(ch) )
			{
				bugPC = TO_PC(ch);
			}

			if( !bugPC )
				return;

			// 가까운 마을로
			int nearZone;
			int nearZonePos;
			CZone* pZone = gserver->FindNearestZone(bugPC->m_pZone->m_index, GET_X(bugPC), GET_Z(bugPC), &nearZone, &nearZonePos);
			if (pZone == NULL)
				return;

			GoZone(bugPC, nearZone,
				   pZone->m_zonePos[nearZonePos][0],															// ylayer
				   GetRandom(pZone->m_zonePos[nearZonePos][1], pZone->m_zonePos[nearZonePos][3]) / 2.0f,		// x
				   GetRandom(pZone->m_zonePos[nearZonePos][2], pZone->m_zonePos[nearZonePos][4]) / 2.0f);		// z

			GAMELOG << init("PD_BUG", bugPC)
					<< end;
			return;
		}

		int ret = ProcAttack(ch, tch, ch->GetAttackType(NULL), NULL, 0);
		if (ret == -1)
			return ;
	}
}
void do_GMSummon(CPC *a1, char *a2)
{
    int v3; // [sp+28h] [bp-20h]@21
    int v4; // [sp+2Ch] [bp-1Ch]@21
    CNPC *v6; // [sp+34h] [bp-14h]@12
    int v8; // [sp+3Ch] [bp-Ch]@10
    char v9; // [sp+43h] [bp-5h]@5
    char *s; // [sp+44h] [bp-4h]@4

    if(a2)
    {
        if(*a2)
        {
            TrimString(a2);
            s = a2;
            if(strlen(a2))
            {
                v9 = 0;
                while(*s)
                {
                    if(!(*(short *)(_ctype_b + 2 * *s) & 0x800))
                    {
                        v9 = 1;
                        break;
                    }
                    ++s;
                }

                v8 = -1;

                if(!v9)
                    v8 = atoi(a2);

                v6 = 0;

                if(v9)
                {
                    for(int i = 0; i < gserver.Unk452200.Unk4; ++i)
                    {
                        if(!strcmp(gserver.Unk452200.Unk0[i].Unk4, a2))
                        {
                            v6 = gserver.Unk452200.Create(gserver.Unk452200.Unk0[i].Unk0);
                            break;
                        }
                    }
                }
                else
                {
                    v6 = gserver.Unk452200.Create(v8);
                }

                if(v6)
                {
                    v6->Unk120.Unk0  = a1->Unk120.Unk0 + 2.0;
                    v6->Unk120.Unk16 = a1->Unk120.Unk16;
                    v6->Unk120.Unk4  = a1->Unk120.Unk4 + 2.0;
                    v6->Unk120.Unk12 = GetRandom(0, 62831) / 10000;

                    v6->Unk476 = v6->Unk120.Unk0;
                    v6->Unk480 = v6->Unk120.Unk16;
                    v6->Unk484 = v6->Unk120.Unk4;
                    v6->Unk752 = 0;

                    a1->Unk412->AddNPC(v6);
                    a1->Unk412->PointToCellNum(v6->Unk120.Unk0, v6->Unk120.Unk4, &v4, &v3);
                    a1->Unk412->CharToCell(v6, v6->Unk120.Unk16, v4, v3);

                    CNetMsg v2;

                    AppearMsg(v2, v6, 1);
                    a1->Unk412->SendToCell(v2, v6->Unk120.Unk16, v4, v3, 4);
                }
            }
        }
    }
}
Exemple #24
0
void M_Reanimate (edict_t *ent, edict_t *target, int r_level, float r_modifier, qboolean printMsg)
{
	vec3_t	bmin, bmax;
	edict_t *e;

	if (!strcmp(target->classname, "drone"))
	{
		// if the summoner is a player, check for sufficient monster slots
		if (ent->client && (ent->num_monsters + target->monsterinfo.control_cost > MAX_MONSTERS))
			return;

		target->monsterinfo.level = r_level;
		M_SetBoundingBox(target->mtype, bmin, bmax);

		if (G_IsValidLocation(target, target->s.origin, bmin, bmax) && M_Initialize(ent, target))
		{
			// restore this drone
			target->monsterinfo.slots_freed = false; // reset freed flag
			target->health = r_modifier*target->max_health;
			target->monsterinfo.power_armor_power = r_modifier*target->monsterinfo.max_armor;
			target->monsterinfo.resurrected_time = level.time + 10.0;
			target->activator = ent; // transfer ownership!
			target->nextthink = level.time + 1.0;
			gi.linkentity(target);
			target->monsterinfo.stand(target);

			ent->num_monsters += target->monsterinfo.control_cost;

			// make sure invasion monsters hunt for navi
			if (invasion->value && !ent->client && ent->activator && !ent->activator->client)
			{
				target->monsterinfo.aiflags &= ~AI_STAND_GROUND;
				target->monsterinfo.aiflags |= AI_FIND_NAVI;
			}

			if (ent->client && printMsg)
				gi.cprintf(ent, PRINT_HIGH, "Resurrected a %s. (%d/%d)\n", target->classname, 
					ent->num_monsters, MAX_MONSTERS);
		}
	}
	else if ((!strcmp(target->classname, "bodyque") || !strcmp(target->classname, "player")))
	{
		int		random=GetRandom(1, 3);
		vec3_t	start;

		// if the summoner is a player, check for sufficient monster slots
		if (ent->client && (ent->num_monsters + 1 > MAX_MONSTERS))
			return;

		e = G_Spawn();

		VectorCopy(target->s.origin, start);

		// kill the corpse
		T_Damage(target, target, target, vec3_origin, target->s.origin, 
			vec3_origin, 10000, 0, DAMAGE_NO_PROTECTION, 0);

		//4.2 random soldier type with different weapons
		if (random == 1)
		{
			// blaster
			e->mtype = M_SOLDIER;
			e->s.skinnum = 0;
		}
		else if (random == 2)
		{
			// rocket
			e->mtype = M_SOLDIERLT;
			e->s.skinnum = 4;
		}
		else
		{
			// shotgun
			e->mtype = M_SOLDIERSS;
			e->s.skinnum = 2;
		}

		e->activator = ent;
		e->monsterinfo.level = r_level;
		M_Initialize(ent, e);
		e->health = r_modifier*e->max_health;
		e->monsterinfo.power_armor_power = r_modifier*e->monsterinfo.max_armor;
		e->monsterinfo.resurrected_time = level.time + 10.0;
		e->s.skinnum |= 1; // injured skin

		e->monsterinfo.stand(e);
		
		if (!G_IsValidLocation(target, start, e->mins, e->maxs))
		{
			start[2] += 24;
			if (!G_IsValidLocation(target, start, e->mins, e->maxs))
			{
				G_FreeEdict(e);
				return;
			}
		}

		VectorCopy(start, e->s.origin);
		gi.linkentity(e);
		e->nextthink = level.time + 1.0;

		ent->num_monsters += e->monsterinfo.control_cost;

		// make sure invasion monsters hunt for navi
		if (invasion->value && !ent->client && ent->activator && !ent->activator->client)
		{
			target->monsterinfo.aiflags &= ~AI_STAND_GROUND;
			target->monsterinfo.aiflags |= AI_FIND_NAVI;
		}

		if (ent->client && printMsg)
			gi.cprintf(ent, PRINT_HIGH, "Resurrected a soldier. (%d/%d)\n", ent->num_monsters, MAX_MONSTERS);
	}
	else if (!strcmp(target->classname, "spiker"))
	{
		// if the summoner is a player, check for sufficient spiker slots
		if (ent->client && (ent->num_spikers + 1 > SPIKER_MAX_COUNT))
			return;

		e = CreateSpiker(ent, r_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_spikers--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->health = r_modifier * e->max_health;
		e->monsterinfo.resurrected_time = level.time + 10.0;
		e->s.frame = 4;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);

		if (ent->client && printMsg)
			gi.cprintf(ent, PRINT_HIGH, "Resurrected a spiker. (%d/%d)\n", ent->num_spikers, SPIKER_MAX_COUNT);
	}
	else if (!strcmp(target->classname, "obstacle"))
	{
		// if the summoner is a player, check for sufficient obstacle slots
		if (ent->client && (ent->num_obstacle + 1 > OBSTACLE_MAX_COUNT))
			return;

		e = CreateObstacle(ent, r_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_obstacle--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->monsterinfo.resurrected_time = level.time + 10.0;
		e->health = r_modifier * e->max_health;
		e->s.frame = 6;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);

		if (ent->client && printMsg)
			gi.cprintf(ent, PRINT_HIGH, "Resurrected an obstacle. (%d/%d)\n", ent->num_obstacle, OBSTACLE_MAX_COUNT);
	}
	else if (!strcmp(target->classname, "gasser"))
	{
		// if the summoner is a player, check for sufficient gasser slots
		if (ent->client && (ent->num_gasser + 1 > GASSER_MAX_COUNT))
			return;

		e = CreateGasser(ent, r_level);

		// make sure the new entity fits
		if (!G_IsValidLocation(target, target->s.origin, e->mins, e->maxs))
		{
			ent->num_gasser--;
			G_FreeEdict(e);
			return;
		}
		
		VectorCopy(target->s.angles, e->s.angles);
		e->s.angles[PITCH] = 0;
		e->monsterinfo.cost = target->monsterinfo.cost;
		e->monsterinfo.resurrected_time = level.time + 10.0;
		e->health = r_modifier * e->max_health;
		e->s.frame = 0;
		VectorCopy(target->s.origin, e->s.origin);
		gi.linkentity(e);

		organ_remove(target, false);

		if (ent->client && printMsg)
			gi.cprintf(ent, PRINT_HIGH, "Resurrected a gasser. (%d/%d)\n", ent->num_gasser, GASSER_MAX_COUNT);
	}
		
}
void do_Attack(CPC* pc, CNetMsg::SP& msg)
{
	CDratanCastle * pCastle = CDratanCastle::CreateInstance();
	pCastle->CheckRespond(pc);

	RequestClient::doAttack* packet = reinterpret_cast<RequestClient::doAttack*>(msg->m_buf);

	// 동시 공격은 최대 5
	if (packet->multicount > 5)
	{
		LOG_ERROR("HACKING : invalid multi count[%d]. charIndex[%d]", packet->multicount, pc->m_index);
		pc->m_desc->Close("invalid multi count");
		return;
	}

	// multi target의 중복 검사
	if (packet->multicount > 1)
	{
		std::set<int> tset;
		for (int i = 0; i < packet->multicount; ++i)
		{
			if (tset.insert(packet->list[i].index).second == false)
			{
				LOG_ERROR("HACKING : duplicate multi target[%d]. charIndex[%d]", packet->list[i].index, pc->m_index);
				pc->m_desc->Close("duplicate multi target");
				return;
			}
		}
	}

	// 대상 검색 : 인접 셀에서만
	CArea* area = pc->m_pArea;
	if (area == NULL)
		return;

	CCharacter* ch = area->FindCharInCell(pc, packet->aIndex, (MSG_CHAR_TYPE)packet->aCharType);
	if (ch == NULL)
		return;

	CCharacter* tch = area->FindCharInCell(ch, packet->tIndex, (MSG_CHAR_TYPE)packet->tCharType);
	if (tch == NULL)
		return;

	// 공격자가 PC이면 자신의 캐릭만 조정
	if (IS_PC(ch) && ch != pc)
		return ;

	switch (ch->m_type)
	{
	case MSG_CHAR_PC:
		{
			if( IS_NPC(tch))
			{
				CPC * pPC = TO_PC(ch);
				CNPC * pNPC = TO_NPC(tch);
				if( pPC->GetSummonNpc(SUMMON_NPC_TYPE_MERCENARY) == pNPC )
					return;
			}

			//pvp보호 아이템 체크
			if (checkPvPProtect(pc, tch) == false)
				return;

			// 공격 거리 검사
			if (GetDistance(ch, tch) > ch->m_attackRange * 2)
				return ;

			// 공속 검사
			if ( ch->ChekAttackType() && ch->CheckHackAttack(pc))
				return ;

			// 펫 타고 있으면 불가능
			if (pc->GetPet() && pc->GetPet()->IsMount())
				return ;

			// 공성 아이템 착용시 해당 스킬 발동
			int mixSkillIndex[] = { pc->m_opSturnIndex, pc->m_opBloodIndex, pc->m_opPoisonIndex, pc->m_opSlowIndex, pc->m_opMoveIndex };
			int mixSkillLevel[] = { pc->m_opSturnLevel, pc->m_opBloodLevel, pc->m_opPoisonLevel, pc->m_opSlowLevel, pc->m_opMoveLevel };
			CSkill* skillMixItem = NULL;
			int i;
			int bStop = 0;
			for (i = 0; i < 5; i++)
			{
				if (mixSkillIndex[i] > 0 && mixSkillLevel[i] > 0)
				{
					skillMixItem = gserver->m_skillProtoList.Create(mixSkillIndex[i], mixSkillLevel[i]);
					if (skillMixItem)
					{
						bool bApply;
						bStop = ApplySkill(ch, tch, skillMixItem, -1, bApply);
					}
					delete skillMixItem;
					skillMixItem = NULL;
					if (bStop != 0)
						return ;
				}
			}

			if (IS_PC(ch))
			{
				CPC* pPCAttacker = TO_PC(ch);
				CItem* weaponItem = pPCAttacker->m_wearInventory.wearItemInfo[WEARING_WEAPON];

				// 암흑 공격
				if (pPCAttacker->m_opAttackBlind > 0)
				{
					CSkill* pSkillBlind = gserver->m_skillProtoList.Create(415, pPCAttacker->m_opAttackBlind);
					int nRetApplySkill = 0;
					if (pSkillBlind)
					{
						bool bApply;
						nRetApplySkill = ApplySkill(ch, tch, pSkillBlind, -1, bApply);
					}
					delete pSkillBlind;
					pSkillBlind = NULL;
					if (nRetApplySkill != 0)
						return ;
				}

				// 독 공격
				if (pPCAttacker->m_opAttackPoison > 0)
				{
					CSkill* pSkillPoison = gserver->m_skillProtoList.Create(414, pPCAttacker->m_opAttackPoison);
					int nRetApplySkill = 0;
					if (pSkillPoison)
					{
						bool bApply;
						nRetApplySkill = ApplySkill(ch, tch, pSkillPoison, -1, bApply);
					}
					delete pSkillPoison;
					pSkillPoison = NULL;
					if (nRetApplySkill != 0)
						return ;
				}
			}
		} // PC 검사

		break;

	case MSG_CHAR_PET:
	case MSG_CHAR_ELEMENTAL:
		// TODO : 소환수 공속 검사
		// 공격 거리 검사
		if (GetDistance(ch, tch) > ch->m_attackRange * 2)
			return ;

		// 공속 검사
		if (ch->CheckHackAttack(pc))
			return ;

		break;

	default:
		break;
	}

	if(IS_PC(tch))
	{
		if( TO_PC(tch)->m_bImmortal == true )
			return;
	}

	if (DEAD(ch) || !ch->CanAttack() || pc->IsDisable())	return ;
	// 결계걸린 대상은 공격 못한다.
	if ( tch->m_assist.m_state & AST_FREEZE )	return;
	//무적 버프 대상은 공격할 수 없다.
	if ( tch->m_assist.m_state & AST_SAFEGUARD )
	{
		CNetMsg::SP rmsg(new CNetMsg);
		SysMsg(rmsg, MSG_SYS_DO_NOT_ATTACK_IMMOTAL);
		SEND_Q(rmsg, pc->m_desc);
		return;
	}


	// 대상이 NPC일때만 멀티 공격
	if (!IS_NPC(tch))
		packet->multicount = 0;

	// 최소한 공격 1회 이상
	bool bAttacked = false;
	bool bAttackedPet = false;		// 애완동물은 NPC상대시 레벨 검사

	// 멀티 공격 검사용
	std::set<int> listMultiTarget;

	while (tch)
	{
		bool bBlocked = false;

		// NPC를 공격할 때에만 속성맵 검사 (프리PK 지역이 아닐때만)
		if ( IS_NPC(tch) && !(tch->GetMapAttr() & MATT_FREEPKZONE) )
		{
			char tempy = GET_YLAYER(ch);
			bBlocked = (!area->IsNotBlocked(ch, tch, true, tempy));
		}

		int ret = 0;
		if (!bBlocked)
		{
			if (IS_PC(ch) && ch->IsEnemy(tch))
			{
				bAttacked = true;
#ifdef MONSTER_AI
				if (tch != NULL	&& IS_NPC(tch))
				{
					CNPC * pTemp = TO_NPC(tch);
					if (pTemp != NULL)
					{
						if (ch->m_level - tch->m_level <= 5 && pTemp->m_proto->m_index != 303 /*악마의 묘지*/)
						{
							bAttackedPet = true;
						}

						if (pTemp->m_bMoveLock || pTemp->m_bMoveToRegen)
						{
							pTemp->m_bMoveToRegen = false;
							pTemp->m_bMoveLock = false;
							pTemp->m_pulseMoveLock = 0;
							pTemp->m_postregendelay = 0;
						}
					}
				}
#else
				if (tch != NULL	&& IS_NPC(tch) && ch->m_level - tch->m_level <= 5)
				{
					CNPC * pTemp = TO_NPC(tch);
					if (pTemp != NULL && pTemp->m_proto->m_index != 303 /*악마의 묘지*/)
					{
						bAttackedPet = true;
					}
				}
#endif
			}

			listMultiTarget.insert(tch->m_index);
			ret = ProcAttack(ch, tch, ch->GetAttackType(NULL), NULL, 0);
		}

		if (ret == -1 || tch->m_index == -1) // ProcAttack()안에서 Character 객체가 소멸된 경우도 포함
		{
			tch = NULL;
			continue ;
		}

		//공격 발동형 스킬 추가
		if( pc->m_optionAttSkillList.count() > 0 )
		{
			//공격 할 시에 적에게 스킬 적용
			void* pos = pc->m_optionAttSkillList.GetHeadPosition();
			bool bApply = false;
			while (pos)
			{
				CSkill* skill = pc->m_passiveSkillList.GetNext(pos);
				if (skill && skill->m_proto)
				{
					int rand = GetRandom(1, 10000);
					if( rand < skill->m_optionSkillProb )
					{
						ApplySkill(ch, tch, skill, -1, bApply);
						if(bApply == false)
						{
							GAMELOG << init("EVENT_PCBANG_2NDS SKILL FAILED (LOGIN) ", pc ) << end;// 스킬 적용 실패
						}
					}
				}
			}
		}

		if (area->m_zone->IsPersonalDungeon() == false)
		{
			tch = NULL;
			continue;
		}

		if (packet->multicount && !DEAD(ch))
		{
			int multitarget = packet->list[packet->multicount].index;
			--packet->multicount;

			tch = area->FindCharInCell(ch, multitarget, (MSG_CHAR_TYPE)packet->tCharType);
			if (tch == NULL)
			{
				continue;
			}

			if (GetDistance(ch, tch) > ch->m_attackRange * 2)
			{
				tch = NULL;
				continue;
			}

			std::set<int>::iterator it = listMultiTarget.find(tch->m_index);
			if (it != listMultiTarget.end())
			{
				GAMELOG << init("HACK ATTACK MULTI TARGET", pc)
						<< "ZONE" << delim
						<< pc->m_pZone->m_index << delim
						<< "TARGET" << delim
						<< packet->tCharType << delim
						<< multitarget
						<< end;

				if (pc->m_desc->IncreaseHackCount(1))
					return ;

				tch = NULL;
			}
		}
		else
		{
			tch = NULL;
			continue;
		}

		if (packet->multicount <= 0)
		{
			tch = NULL;
			continue;
		}
	} // end while

	if (bAttackedPet && !ch->IsInPeaceZone(true))
		pc->m_pulseLastAttackSkill = gserver->m_pulse;

#ifdef EVENT_SEARCHFRIEND_TIME
	// 공격시 이벤트 시간 갱신 검사
	if (gserver->m_bSearchFriendEvent && (pc->m_nEventSearchFriendListCount >= 1)
			&& (pc->m_bEventSearchFriendSelect == true) && (pc->m_nTimeEventSearchFriend <= 216000)
			&& bAttacked && !ch->IsInPeaceZone(true))
		pc->m_pulseEventSearchFriend = gserver->m_pulse;
#endif // #ifdef EVENT_SEARCHFRIEND_TIME
}
void Body::HandleModelString(ArgList* pArgList)
{
    if (!g_pLTServer || !pArgList || !pArgList->argv || pArgList->argc == 0) return;

	char* pKey = pArgList->argv[0];
	if (!pKey) return;

	LTBOOL bSlump = !_stricmp(pKey, s_szKeyNoise);
	LTBOOL bLand = !_stricmp(pKey, s_szKeyLand);

	if ( bSlump || bLand )
	{
		// Hitting the ground noise
/*
		SurfaceType eSurface = ST_UNKNOWN;
		CollisionInfo Info;
        g_pLTServer->GetStandingOn(m_hObject, &Info);

		if (Info.m_hPoly && Info.m_hPoly != INVALID_HPOLY)
		{
			eSurface = (SurfaceType)GetSurfaceType(Info.m_hPoly);
		}
		else if (Info.m_hObject) // Get the texture flags from the object...
		{
			eSurface = (SurfaceType)GetSurfaceType(Info.m_hObject);
		}
		else
		{
			return;
		}
*/

		LTVector vPos;
        g_pLTServer->GetObjectPos(m_hObject, &vPos);

		IntersectQuery IQuery;
		IntersectInfo IInfo;

		IQuery.m_From = vPos;
		IQuery.m_To = vPos - LTVector(0,96,0);
		IQuery.m_Flags = INTERSECT_OBJECTS | INTERSECT_HPOLY | IGNORE_NONSOLID;
		IQuery.m_FilterFn = GroundFilterFn;

		SurfaceType eSurface;

		g_cIntersectSegmentCalls++;
        if (g_pLTServer->IntersectSegment(&IQuery, &IInfo))
		{
			if (IInfo.m_hPoly && IInfo.m_hPoly != INVALID_HPOLY)
			{
				eSurface = (SurfaceType)GetSurfaceType(IInfo.m_hPoly);
			}
			else if (IInfo.m_hObject) // Get the texture flags from the object...
			{
				eSurface = (SurfaceType)GetSurfaceType(IInfo.m_hObject);
			}
			else
			{
				return;
			}
		}
		else
		{
			return;
		}

		SURFACE* pSurf = g_pSurfaceMgr->GetSurface(eSurface);
		_ASSERT(pSurf);
		if (!pSurf) return;

		// Update the noise info. We use a time in the future so AI's don't *instantly* react to the sound
		// AI's twice as sensitive to landing sound (because it's louder)

        m_DeathScene.SetNoise(pSurf->fDeathNoiseModifier * (bLand ? 2.0f : 1.0f), g_pLTServer->GetTime() + GetRandom(0.5f, 1.0f));
	}
}
Exemple #27
0
void CLineSystemFX::AddLine(int nIndex, LTBOOL bSetInitialPos)
{
	if (!m_hServerObject || !m_pLines || nIndex < 0 || nIndex >= m_nTotalNumLines) return;

    LTVector vPos, vCamPos, vObjPos, vDist, vVel;
    LTLine line;

	g_pLTClient->GetObjectPos(m_hServerObject, &vObjPos);

	// Get the camera's position...If the camera is too far away from
	// the line being added, don't add it :)

	HOBJECT hCamera = g_pPlayerMgr->GetCamera();
	if (!hCamera) return;

	g_pLTClient->GetObjectPos(hCamera, &vCamPos);
	vCamPos.y = 0.0f;  // Only take x/z into account...

	vPos.x = GetRandom(-m_cs.vDims.x, m_cs.vDims.x);
	vPos.y = GetRandom(-m_cs.vDims.y, m_cs.vDims.y);
	vPos.z = GetRandom(-m_cs.vDims.z, m_cs.vDims.z);

    LTFLOAT fLifetime = m_cs.fLineLifetime;

	vVel.x = GetRandom(m_cs.vMinVel.x, m_cs.vMaxVel.x);
	vVel.y = GetRandom(m_cs.vMinVel.y, m_cs.vMaxVel.y);
	vVel.z = GetRandom(m_cs.vMinVel.z, m_cs.vMaxVel.z);


	// If we need to set the initial line pos...

	if (bSetInitialPos)
	{
		fLifetime = GetRandom(0.0f, m_cs.fLineLifetime);

		if (fLifetime >= 0.0f)
		{
			vPos += (vVel * (m_cs.fLineLifetime - fLifetime));
		}
		else
		{
			fLifetime = m_cs.fLineLifetime;
		}
	}


	vObjPos += vPos;
	vObjPos.y = 0.0f; // Only take x/z into account

	vDist = vCamPos - vObjPos;

	if (vDist.MagSqr() < m_fMaxViewDistSqr || bSetInitialPos)
	{
		line.m_Points[0].m_Pos = vPos + m_vStartOffset;
		line.m_Points[0].r	   = m_cs.vStartColor.x;
		line.m_Points[0].g	   = m_cs.vStartColor.y;
		line.m_Points[0].b	   = m_cs.vStartColor.z;
		line.m_Points[0].a	   = m_cs.fStartAlpha;

		line.m_Points[1].m_Pos = vPos + m_vEndOffset;
		line.m_Points[1].r	   = m_cs.vEndColor.x;
		line.m_Points[1].g	   = m_cs.vEndColor.y;
		line.m_Points[1].b	   = m_cs.vEndColor.z;
		line.m_Points[1].a	   = m_cs.fEndAlpha;

        if (m_pLines[nIndex].hLTLine)
		{
            m_pClientDE->SetLineInfo(m_pLines[nIndex].hLTLine, &line);
		}
		else
		{
            m_pLines[nIndex].hLTLine = m_pClientDE->AddLine(m_hObject, &line);

			m_snTotalLines++;
		}

		m_pLines[nIndex].fLifetime	= fLifetime;
		m_pLines[nIndex].vVel		= vVel;
	}
	else
	{
		RemoveLine(nIndex);
	}
}
int main(int argc, char *argv[])
{
    #include "setRootCase.H"
    #include "createTime.H"
    #include "createMesh.H"
    #include "createFields.H"

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //


    Info << "\n setting particle positions \n" << endl;

    word positioningType
    (
        setParticlePositionsPelletDict.lookup("positioningType")
    );

    if(positioningType == "pellet")
    {   
        dictionary autoPelletPositionSubDict
        (
            setParticlePositionsPelletDict.subDict("autoPelletPositionSubDict")
        );

        scalar particleDiameter
        (
            readScalar(autoPelletPositionSubDict.lookup("particleDiameter"))
        );

        label particleNumber
        (
            readLabel(autoPelletPositionSubDict.lookup("particleNumber"))
        );

        scalar radius
        (
            readScalar(autoPelletPositionSubDict.lookup("radius"))
        );

        scalar length
        (
            readScalar(autoPelletPositionSubDict.lookup("length"))
        );

        vector origin
        (
            autoPelletPositionSubDict.lookup("origin")
        );

        label trialNum
        (
            readLabel(autoPelletPositionSubDict.lookup("trialNumber"))
        );

        label densityR
        (
            readLabel(autoPelletPositionSubDict.lookup("densityRadius"))
        );

        label densityT
        (
            readLabel(autoPelletPositionSubDict.lookup("densityTheta"))
        );

        label densityL
        (
            readLabel(autoPelletPositionSubDict.lookup("densityLength"))
        );


        // Min and Max of each variable were multiplied by densityR,T,L respectively to increase the resolution, since random function I made can only output integer.
        // by doing so, it can output decimal value.
        scalar thetaMin = 0*densityT;
        scalar thetaMax = 360 * densityT;
        scalar rMin = 0*densityR;
        scalar rMax = radius * densityR;
        scalar lMin = -(length-particleDiameter)*densityL/2;
        scalar lMax = (length-particleDiameter)*densityL/2;

        //dummy list to store particles in cylindrical coordinates x is r, y is theta, z is length

        List<vector> dummyCylindic(trialNum);

        //dummy list to store particles in rectangula coordinates

        List<vector> dummyRectangula(trialNum);

        //List for particles settled in cylindrical coordinates

        List<vector> cylindic(particleNumber);

        //List for particles transformed into rectangular coordinates

        List<vector> rectangula(particleNumber);

        // the first particle is stored in cylindic and rectangula list

        cylindic[0].x() = GetRandom(rMin,rMax)/densityR;
        cylindic[0].y() = GetRandom(thetaMin,thetaMax)/densityT;
        cylindic[0].z() = GetRandom(lMin,lMax)/densityL;

        Info << "r is" << cylindic[0].x() << endl;
        Info << "theta is" << cylindic[0].y() << endl;
        Info << "length is " << cylindic[0].z() << endl;


        // cylindic[0] is transormed into rectangular coordinates
        //inside sin is written in radian

        rectangula[0].x() = cylindic[0].x()*Foam::sin(constant::mathematical::pi*cylindic[0].y()/180);
        rectangula[0].y() = cylindic[0].z();
        rectangula[0].z() = cylindic[0].x()*Foam::cos(constant::mathematical::pi*cylindic[0].y()/180);

        Info << "x is" << rectangula[0].x() << endl;
        Info << "y is" << rectangula[0].y() << endl;
        Info << "z is " << rectangula[0].z() << endl;
        
        label l = 0;
        forAll(dummyCylindic,i)
        {
            if( l< particleNumber-1 )
            {
                dummyCylindic[i].x() = GetRandom(rMin,rMax)/densityR;
                dummyCylindic[i].y() = GetRandom(thetaMin,thetaMax)/densityT;
                dummyCylindic[i].z() = GetRandom(lMin,lMax)/densityL;
                Info << " dummyCylindic[ "<<i<<"].x()" << dummyCylindic[i].x() << endl;
                Info << " dummyCylindic[ "<<i<<"].y()" << dummyCylindic[i].y() << endl;
                Info << " dummyCylindic[ "<<i<<"].z()" << dummyCylindic[i].z() << endl;

                dummyRectangula[i].x() = dummyCylindic[i].x()*Foam::sin(constant::mathematical::pi*dummyCylindic[i].y()/180);
                dummyRectangula[i].y() = dummyCylindic[i].z();
                dummyRectangula[i].z() = dummyCylindic[i].x()*Foam::cos(constant::mathematical::pi*dummyCylindic[i].y()/180);
    
                label counter = 0;
                label t;
                for(t=0; t<=l; t++)
                {
                    scalar S;
                    S = mag(dummyRectangula[i]-rectangula[t]);
                    if(S>particleDiameter)
                    {
                        counter += 1;   
                    }else{
                        counter += 0;
                    }
                }
             
                if(counter == l+1)
                {
                    l = l+1;
                    rectangula[l] = dummyRectangula[i];
                }
            }
        } 
        

        fileName rootName(runTime.path());
        fileName fName("particlePositionsPellet");   
        OFstream os(rootName/fName);
        Info<< "Writing to the output file"<<endl;

        label k;
        for(k=0; k<=l; k++)
        {
            rectangula[k] += origin ;
        }

        for(k=0; k<=l; k++)
        {
            os <<"("<<rectangula[k].x()<<"  "<<rectangula[k].y()<<"  "<<rectangula[k].z()<<")"<<endl;
        }


        
        Info<< "End\n" << endl;
    }
Exemple #29
0
void CLaserBeam::Update(LTVector &vBeamStartPos, const LTRotation* pRDirRot,
                        LTBOOL b3rdPerson, LTBOOL bDetect)
{
	if (!m_bOn) return;

	// Calculate beam position...

	HOBJECT hCamera = g_pPlayerMgr->GetCamera();
	if (!hCamera) return;

    HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject();
	if (!hPlayerObj) return;

    HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL};

	IntersectQuery qInfo;
	IntersectInfo iInfo;

    LTVector vPos(0, 0, 0);
    LTRotation rRot;

    LTVector vU, vR, vF;

	if (pRDirRot && b3rdPerson)
	{
		vPos = vBeamStartPos;

		vU = pRDirRot->Up();
		vR = pRDirRot->Right();
		vF = pRDirRot->Forward();
	}
	else
	{
		g_pLTClient->GetObjectRotation(hCamera, &rRot);
		g_pLTClient->GetObjectPos(hCamera, &vPos);

		vU = rRot.Up();
		vR = rRot.Right();
		vF = rRot.Forward();

		if (g_cvarLaserBeamDebug.GetFloat() == 0.0f)
		{
			vBeamStartPos += vPos;
		}
		else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f)
		{
			vBeamStartPos = vPos;
		}
		else if (pRDirRot)
		{
			vU = pRDirRot->Up();
			vR = pRDirRot->Right();
			vF = pRDirRot->Forward();
			vBeamStartPos = vBeamStartPos;
		}

	}


    LTVector vEndPos = vPos + (vF * 10000.0f);

	qInfo.m_From = vPos;
	qInfo.m_To   = vEndPos;

	qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID;
	qInfo.m_FilterFn = ObjListFilterFn;
	qInfo.m_pUserData = hFilterList;

    if (g_pLTClient->IntersectSegment(&qInfo, &iInfo))
	{
		vEndPos = iInfo.m_Point;
	}


	// Show the light beam...

    LTVector vColor = LTVector(GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f), GetRandom(35.0f, 55.0f));;

    LTFLOAT fAlpha = g_cvarLaserBeamAlpha.GetFloat();

	if (iInfo.m_hObject && bDetect)
	{
        uint32 dwUsrFlgs = 0;
        g_pCommonLT->GetObjectFlags(iInfo.m_hObject, OFT_User, dwUsrFlgs);

		if (dwUsrFlgs & USRFLG_CHARACTER)
		{
			fAlpha	= 0.95f;
			vColor.Init(GetRandom(35.0f, 55.0f), GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f));;
		}
	}

    LTFLOAT fWidth = g_cvarLaserBeamThickness.GetFloat();
	fWidth = b3rdPerson ? fWidth*2.0f : fWidth;

	vBeamStartPos += (vF * g_cvarLaserBeamFOffset.GetFloat());
	vBeamStartPos += (vR * g_cvarLaserBeamROffset.GetFloat());
	vBeamStartPos += (vU * g_cvarLaserBeamUOffset.GetFloat());

	PLFXCREATESTRUCT pls;

	if (g_cvarLaserBeamDebug.GetFloat() >= 0.0f)
	{
        // g_pLTClient->CPrint("StartPos = %.2f, %.2f, %.2f", VEC_EXPAND(vBeamStartPos));
        // g_pLTClient->CPrint("EndPos = %.2f, %.2f, %.2f", VEC_EXPAND(vEndPos));
	}

	pls.vStartPos			= vBeamStartPos;
	pls.vEndPos				= vEndPos;
	pls.vInnerColorStart	= vColor;
	pls.vInnerColorEnd		= pls.vInnerColorStart;
    pls.vOuterColorStart    = LTVector(0, 0, 0);
    pls.vOuterColorEnd      = LTVector(0, 0, 0);
	pls.fAlphaStart			= fAlpha;
	pls.fAlphaEnd			= fAlpha;
	pls.fMinWidth			= 0;
	pls.fMaxWidth			= fWidth;
	pls.fMinDistMult		= 1.0f;
	pls.fMaxDistMult		= 1.0f;
	pls.fLifeTime			= 1.0f;
	pls.fAlphaLifeTime		= 1.0f;
	pls.fPerturb			= 0.0f;
    pls.bAdditive           = LTTRUE;
    pls.bAlignFlat          = b3rdPerson ? LTFALSE : LTTRUE;
	pls.nWidthStyle			= PLWS_CONSTANT;
	pls.nNumSegments		= (int)g_cvarLaserBeamNumSegments.GetFloat();

	if (m_LightBeam.HasBeenDrawn())
	{
		// Keep the light beam in the vis list...

		m_LightBeam.SetPos(vBeamStartPos);

		// Hide the beam in portals if 1st person...Also set flag really
		// close to true...

        uint32 dwFlags2, dwFlags;

		dwFlags = m_LightBeam.GetFlags();
		dwFlags2 = m_LightBeam.GetFlags2();

		if (b3rdPerson)
		{
			dwFlags &= ~FLAG_REALLYCLOSE;
		}
		else
		{
			if (g_cvarLaserBeamDebug.GetFloat() > 1.0f)
			{
				dwFlags |= FLAG_REALLYCLOSE;
                pls.bUseObjectRotation = LTTRUE;
			}
		}

		m_LightBeam.SetFlags(dwFlags);
		m_LightBeam.SetFlags2(dwFlags2);

		m_LightBeam.ReInit(&pls);
	}
	else
	{
		m_LightBeam.Init(&pls);
        m_LightBeam.CreateObject(g_pLTClient);
	}


	m_LightBeam.Update();
}
		/** Handles movement of joined local player. */
		void Client::UpdateLocalPlayer(float dt) {
			SPADES_MARK_FUNCTION();
			
			auto *player = world->GetLocalPlayer();
			
			PlayerInput inp = playerInput;
			WeaponInput winp = weapInput;
			
			// weapon/tools are disabled while/soon after sprinting
			if(GetSprintState() > 0.001f) {
				winp.primary = false;
				winp.secondary = false;
			}
			
			// don't allow to stand up when ceilings are too low
			if(inp.crouch == false){
				if(player->GetInput().crouch){
					if(!player->TryUncrouch(false)){
						inp.crouch = true;
					}
				}
			}
			
			// don't allow jumping in the air
			if(inp.jump){
				if(!player->IsOnGroundOrWade())
					inp.jump = false;
			}
			
			// weapon/tools are disabled while changing tools
			if(clientPlayers[world->GetLocalPlayerIndex()]->IsChangingTool()) {
				winp.primary = false;
				winp.secondary = false;
			}
			
			// disable weapon while reloading (except shotgun)
			if(player->GetTool() == Player::ToolWeapon &&
			   player->IsAwaitingReloadCompletion() &&
			   !player->GetWeapon()->IsReloadSlow()) {
				winp.primary = false;
			}
			
			player->SetInput(inp);
			player->SetWeaponInput(winp);
			
			//send player input
			// FIXME: send only there are any changed?
			net->SendPlayerInput(inp);
			net->SendWeaponInput(winp);
			
			if(hasDelayedReload) {
				world->GetLocalPlayer()->Reload();
				net->SendReload();
				hasDelayedReload = false;
			}
			
			//PlayerInput actualInput = player->GetInput();
			WeaponInput actualWeapInput = player->GetWeaponInput();
			
			if(actualWeapInput.secondary &&
			   player->IsToolWeapon() &&
			   player->IsAlive()){
			}else{
				if(player->IsToolWeapon()){
					// there is a possibility that player has respawned or something.
					// stop aiming down
					weapInput.secondary = false;
				}
			}
			
			// is the selected tool no longer usable (ex. out of ammo)?
			if(!player->IsToolSelectable(player->GetTool())) {
				// release mouse button before auto-switching tools
				winp.primary = false;
				winp.secondary = false;
				weapInput = winp;
				net->SendWeaponInput(weapInput);
				actualWeapInput = winp = player->GetWeaponInput();
				
				// select another tool
				Player::ToolType t = player->GetTool();
				do{
					switch(t){
						case Player::ToolSpade:
							t = Player::ToolGrenade;
							break;
						case Player::ToolBlock:
							t = Player::ToolSpade;
							break;
						case Player::ToolWeapon:
							t = Player::ToolBlock;
							break;
						case Player::ToolGrenade:
							t = Player::ToolWeapon;
							break;
					}
				}while(!world->GetLocalPlayer()->IsToolSelectable(t));
				SetSelectedTool(t);
			}
			
			// send orientation
			Vector3 curFront = player->GetFront();
			if(curFront.x != lastFront.x ||
			   curFront.y != lastFront.y ||
			   curFront.z != lastFront.z) {
				lastFront = curFront;
				net->SendOrientation(curFront);
			}
			
			lastKills = world->GetPlayerPersistent(player->GetId()).kills;
			
			// show block count when building block lines.
			if(player->IsAlive() &&
			   player->GetTool() == Player::ToolBlock &&
			   player->GetWeaponInput().secondary &&
			   player->IsBlockCursorDragging()) {
				if(player->IsBlockCursorActive()) {
					auto blocks = std::move
					(world->CubeLine(player->GetBlockCursorDragPos(),
									 player->GetBlockCursorPos(),
									 256));
					auto msg = _TrN("Client",
									"{0} block", "{0} blocks",
									blocks.size());
					AlertType type =
					static_cast<int>(blocks.size()) > player->GetNumBlocks() ?
					AlertType::Warning : AlertType::Notice;
					ShowAlert(msg, type, 0.f, true);
				}else{
					// invalid
					auto msg = _Tr("Client", "-- blocks");
					AlertType type = AlertType::Warning;
					ShowAlert(msg, type, 0.f, true);
				}
			}
			
			if(player->IsAlive())
				lastAliveTime = time;
			
			if(player->GetHealth() < lastHealth){
				// ouch!
				lastHealth = player->GetHealth();
				lastHurtTime = world->GetTime();
				
				Handle<IAudioChunk> c;
				switch((rand() >> 3) & 3){
					case 0:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal1.wav");
						break;
					case 1:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal2.wav");
						break;
					case 2:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal3.wav");
						break;
					case 3:
						c = audioDevice->RegisterSound("Sounds/Weapons/Impacts/FleshLocal4.wav");
						break;
				}
				audioDevice->PlayLocal(c, AudioParam());
				
				float hpper = player->GetHealth() / 100.f;
				int cnt = 18 - (int)(player->GetHealth() / 100.f * 8.f);
				hurtSprites.resize(std::max(cnt, 6));
				for(size_t i = 0; i < hurtSprites.size(); i++) {
					HurtSprite& spr = hurtSprites[i];
					spr.angle = GetRandom() * (2.f * static_cast<float>(M_PI));
					spr.scale = .2f + GetRandom() * GetRandom() * .7f;
					spr.horzShift = GetRandom();
					spr.strength = .3f + GetRandom() * .7f;
					if(hpper > .5f) {
						spr.strength *= 1.5f - hpper;
					}
				}
				
			}else{