Exemplo n.º 1
0
void SetupDynamisMob(CMobEntity* PMob)
{
    JOBTYPE mJob = PMob->GetMJob();

    // no gil drop and no mugging!
    PMob->setMobMod(MOBMOD_GIL_MAX, -1);
    PMob->setMobMod(MOBMOD_MUG_GIL, -1);
    PMob->setMobMod(MOBMOD_2HOUR_PROC, 80);

    // used for dynamis stat-spawned mobs
    PMob->m_StatPoppedMobs = false;

    // dynamis mobs have true sight
    if(PMob->m_Aggro & AGGRO_DETECT_SIGHT)
    {
        PMob->m_Aggro |= AGGRO_DETECT_TRUESIGHT;
    }

    if(PMob->m_Aggro & AGGRO_DETECT_HEARING)
    {
        PMob->m_Aggro |= AGGRO_DETECT_TRUEHEARING;
    }

    // Hydra's and beastmen can 2 hour
    if(PMob->m_EcoSystem == SYSTEM_BEASTMEN ||
            PMob->m_EcoSystem == SYSTEM_UNDEAD)
    {
        PMob->setMobMod(MOBMOD_MAIN_2HOUR, 1);
    }

    // boost dynamis mobs weapon damage
    PMob->setMobMod(MOBMOD_WEAPON_BONUS, 135);
    PMob->m_Weapons[SLOT_MAIN]->setDamage(GetWeaponDamage(PMob));

    // never despawn
    PMob->SetDespawnTime(0s);
    PMob->setMobMod(MOBMOD_NO_DESPAWN, 1);

    // do not roam around
    PMob->m_roamFlags |= ROAMFLAG_EVENT;
    PMob->m_maxRoamDistance = 0.5f;

    // job resist traits are much more powerful in dynamis
    // according to wiki
    for(auto&& PTrait : PMob->TraitList)
    {
        uint16 type = PTrait->getMod();

        if(type >= 240 && type <= 255)
        {
            // give mob a total of x4 the regular rate
            PMob->addModifier(type, PTrait->getValue() * 3);
        }
    }
}
	CASW_Shotgun_Pellet*  CASW_Weapon_Shotgun::CreatePellet(Vector vecSrc, Vector newVel, CASW_Marine *pMarine)
	{
		if (!pMarine)
			return NULL;
		AngularImpulse rotSpeed(0,0,720);
		float flDamage = GetWeaponDamage();
		if (asw_debug_marine_damage.GetBool())
			Msg("Weapon dmg = %f\n", flDamage);
		flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale();
		Msg("Creating shotgun pellet\n");
		return CASW_Shotgun_Pellet::Shotgun_Pellet_Create( vecSrc, QAngle(0,0,0),
				newVel, rotSpeed, pMarine, flDamage);
	}
Exemplo n.º 3
0
void CalculateStats(CMobEntity * PMob)
{
    // remove all to keep mods in sync
    PMob->StatusEffectContainer->KillAllStatusEffect();
    PMob->restoreModifiers();
    PMob->restoreMobModifiers();

    bool isNM = PMob->m_Type & MOBTYPE_NOTORIOUS;
    JOBTYPE mJob = PMob->GetMJob();
    JOBTYPE sJob = PMob->GetSJob();
    uint8 mLvl = PMob->GetMLevel();
    ZONETYPE zoneType = PMob->loc.zone->GetType();

    if(PMob->HPmodifier == 0)
    {
        float hpScale = PMob->HPscale;

        if (PMob->getMobMod(MOBMOD_HP_SCALE) != 0)
        {
            hpScale = (float)PMob->getMobMod(MOBMOD_HP_SCALE) / 100.0f;
        }

        float growth = 1.06f;
        float petGrowth = 0.75f;
        float base = 18.0f;

        //give hp boost every 10 levels after 25
        //special boosts at 25 and 50
        if(mLvl > 75)
        {
            growth = 1.28f;
            petGrowth = 1.03f;
        }
        else if(mLvl > 65)
        {
            growth = 1.27f;
            petGrowth = 1.02f;
        }
        else if(mLvl > 55)
        {
            growth = 1.25f;
            petGrowth = 0.99f;
        }
        else if(mLvl > 50)
        {
            growth = 1.21f;
            petGrowth = 0.96f;
        }
        else if(mLvl > 45)
        {
            growth = 1.17f;
            petGrowth = 0.95f;
        }
        else if(mLvl > 35)
        {
            growth = 1.14f;
            petGrowth = 0.92f;
        }
        else if(mLvl > 25)
        {
            growth = 1.1f;
            petGrowth = 0.82f;
        }

        // pets have lower health
        if(PMob->PMaster != nullptr)
        {
            growth = petGrowth;
        }


        PMob->health.maxhp = (int16)(base * pow(mLvl, growth) * hpScale);

        if(isNM)
        {
            PMob->health.maxhp = (int32)(PMob->health.maxhp * 2.0f);
            if(mLvl > 75){
                PMob->health.maxhp = (int32)(PMob->health.maxhp * 2.5f);
            }
        }

    }
    else
    {
        PMob->health.maxhp = PMob->HPmodifier;
    }

    if(isNM)
    {
        PMob->health.maxhp = (int32)(PMob->health.maxhp * map_config.nm_hp_multiplier);
    }
    else
    {
        PMob->health.maxhp = (int32)(PMob->health.maxhp * map_config.mob_hp_multiplier);
    }

    bool hasMp = false;

    switch(mJob){
    case JOB_PLD:
    case JOB_WHM:
    case JOB_BLM:
    case JOB_RDM:
    case JOB_DRK:
    case JOB_BLU:
    case JOB_SCH:
    case JOB_SMN:
        hasMp = true;
        break;
    default:
        break;
    }

    switch(sJob){
    case JOB_PLD:
    case JOB_WHM:
    case JOB_BLM:
    case JOB_RDM:
    case JOB_DRK:
    case JOB_BLU:
    case JOB_SCH:
    case JOB_SMN:
        hasMp = true;
        break;
    default:
        break;
    }

    if(PMob->getMobMod(MOBMOD_MP_BASE))
    {
        hasMp = true;
    }

    if(hasMp)
    {
        float scale = PMob->MPscale;

        if(PMob->getMobMod(MOBMOD_MP_BASE))
        {
            scale = (float)PMob->getMobMod(MOBMOD_MP_BASE) / 100.0f;
        }

        if(PMob->MPmodifier == 0)
        {
            PMob->health.maxmp = (int16)(18.2 * pow(mLvl,1.1075) * scale) + 10;
            if(isNM)
            {
                PMob->health.maxmp = (int32)(PMob->health.maxmp * 1.5f);
                if(mLvl>75)
                {
                    PMob->health.maxmp = (int32)(PMob->health.maxmp * 1.5f);
                }
            }
        }
        else
        {
            PMob->health.maxmp = PMob->MPmodifier;
        }

        if(isNM)
        {
            PMob->health.maxmp = (int32)(PMob->health.maxmp * map_config.nm_mp_multiplier);
        }
        else
        {
            PMob->health.maxmp = (int32)(PMob->health.maxmp * map_config.mob_mp_multiplier);
        }
    }

    PMob->UpdateHealth();

    PMob->health.tp = 0;
    PMob->health.hp = PMob->GetMaxHP();
    PMob->health.mp = PMob->GetMaxMP();

    PMob->m_Weapons[SLOT_MAIN]->setDamage(GetWeaponDamage(PMob));

    //reduce weapon delay of MNK
    if(PMob->GetMJob()==JOB_MNK){
        PMob->m_Weapons[SLOT_MAIN]->resetDelay();
    }

    uint16 fSTR = GetBaseToRank(PMob->strRank, mLvl);
    uint16 fDEX = GetBaseToRank(PMob->dexRank, mLvl);
    uint16 fVIT = GetBaseToRank(PMob->vitRank, mLvl);
    uint16 fAGI = GetBaseToRank(PMob->agiRank, mLvl);
    uint16 fINT = GetBaseToRank(PMob->intRank, mLvl);
    uint16 fMND = GetBaseToRank(PMob->mndRank, mLvl);
    uint16 fCHR = GetBaseToRank(PMob->chrRank, mLvl);

    uint16 mSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),2), mLvl);
    uint16 mDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),3), mLvl);
    uint16 mVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),4), mLvl);
    uint16 mAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),5), mLvl);
    uint16 mINT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),6), mLvl);
    uint16 mMND = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),7), mLvl);
    uint16 mCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),8), mLvl);

    uint16 sSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),2), PMob->GetSLevel());
    uint16 sDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),3), PMob->GetSLevel());
    uint16 sVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),4), PMob->GetSLevel());
    uint16 sAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),5), PMob->GetSLevel());
    uint16 sINT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),6), PMob->GetSLevel());
    uint16 sMND = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),7), PMob->GetSLevel());
    uint16 sCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),8), PMob->GetSLevel());

    if(PMob->GetSLevel() > 15)
    {
        sSTR /= 2;
        sDEX /= 2;
        sAGI /= 2;
        sINT /= 2;
        sMND /= 2;
        sCHR /= 2;
        sVIT /= 2;
    }
    else
    {
        sSTR = 0;
        sDEX = 0;
        sAGI = 0;
        sINT = 0;
        sMND = 0;
        sCHR = 0;
        sVIT = 0;
    }

    PMob->stats.STR = fSTR + mSTR + sSTR;
    PMob->stats.DEX = fDEX + mDEX + sDEX;
    PMob->stats.VIT = fVIT + mVIT + sVIT;
    PMob->stats.AGI = fAGI + mAGI + sAGI;
    PMob->stats.INT = fINT + mINT + sINT;
    PMob->stats.MND = fMND + mMND + sMND;
    PMob->stats.CHR = fCHR + mCHR + sCHR;

    if(isNM)
    {
        PMob->stats.STR = (uint16)(PMob->stats.STR * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.DEX = (uint16)(PMob->stats.DEX * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.VIT = (uint16)(PMob->stats.VIT * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.AGI = (uint16)(PMob->stats.AGI * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.INT = (uint16)(PMob->stats.INT * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.MND = (uint16)(PMob->stats.MND * 1.5f * map_config.nm_stat_multiplier);
        PMob->stats.CHR = (uint16)(PMob->stats.CHR * 1.5f * map_config.nm_stat_multiplier);
    }
    else
    {
        PMob->stats.STR = (uint16)(PMob->stats.STR * map_config.mob_stat_multiplier);
        PMob->stats.DEX = (uint16)(PMob->stats.DEX * map_config.mob_stat_multiplier);
        PMob->stats.VIT = (uint16)(PMob->stats.VIT * map_config.mob_stat_multiplier);
        PMob->stats.AGI = (uint16)(PMob->stats.AGI * map_config.mob_stat_multiplier);
        PMob->stats.INT = (uint16)(PMob->stats.INT * map_config.mob_stat_multiplier);
        PMob->stats.MND = (uint16)(PMob->stats.MND * map_config.mob_stat_multiplier);
        PMob->stats.CHR = (uint16)(PMob->stats.CHR * map_config.mob_stat_multiplier);
    }

    // special case, give spell list to my pet
    if(PMob->getMobMod(MOBMOD_PET_SPELL_LIST) && PMob->PPet != nullptr)
    {
        // Stubborn_Dredvodd
        CMobEntity* PPet = (CMobEntity*)PMob->PPet;

        // give pet spell list
        PPet->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_PET_SPELL_LIST));
    }

    if(PMob->getMobMod(MOBMOD_SPELL_LIST))
    {
        PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_SPELL_LIST));
    }

    // cap all stats for mLvl / job
    for (int i=SKILL_DIV; i <=SKILL_BLU; i++)
    {
        uint16 maxSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetMJob(),mLvl > 99 ? 99 : mLvl);
        if (maxSkill != 0)
        {
            PMob->WorkingSkills.skill[i] = maxSkill;
        }
        else //if the mob is WAR/BLM and can cast spell
        {
            // set skill as high as main level, so their spells won't get resisted
            uint16 maxSubSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetSJob(),mLvl > 99 ? 99 : mLvl);

            if (maxSubSkill != 0)
            {
                PMob->WorkingSkills.skill[i] = maxSubSkill;
            }
        }
    }
    for (int i=SKILL_H2H; i <=SKILL_STF; i++)
    {
        uint16 maxSkill = battleutils::GetMaxSkill(3, mLvl > 99 ? 99 : mLvl);
        if (maxSkill != 0)
        {
            PMob->WorkingSkills.skill[i] = maxSkill;
        }
    }

    PMob->addModifier(Mod::DEF, GetBase(PMob,PMob->defRank));
    PMob->addModifier(Mod::EVA, GetEvasion(PMob));
    PMob->addModifier(Mod::ATT, GetBase(PMob,PMob->attRank));
    PMob->addModifier(Mod::ACC, GetBase(PMob,PMob->accRank));

    //natural magic evasion
    PMob->addModifier(Mod::MEVA, GetMagicEvasion(PMob));

    // add traits for sub and main
    battleutils::AddTraits(PMob, traits::GetTraits(mJob), mLvl);
    battleutils::AddTraits(PMob, traits::GetTraits(PMob->GetSJob()), PMob->GetSLevel());

    SetupJob(PMob);
    SetupRoaming(PMob);

    // All beastmen drop gil
    if (PMob->m_EcoSystem == SYSTEM_BEASTMEN)
    {
        PMob->defaultMobMod(MOBMOD_GIL_BONUS, 100);
    }

    if (PMob->PMaster != nullptr)
    {
        SetupPetSkills(PMob);
    }

    PMob->m_Behaviour |= PMob->getMobMod(MOBMOD_BEHAVIOR);

    if(zoneType == ZONETYPE_DUNGEON)
    {
        SetupDungeonMob(PMob);
    }
    else if(zoneType == ZONETYPE_BATTLEFIELD)
    {
        SetupBattlefieldMob(PMob);
    }
    else if(zoneType == ZONETYPE_DYNAMIS)
    {
        SetupDynamisMob(PMob);
    }

    if(PMob->m_Type & MOBTYPE_NOTORIOUS)
    {
        SetupNMMob(PMob);
    }

    if(PMob->m_Type & MOBTYPE_EVENT)
    {
        SetupEventMob(PMob);
    }

    if(PMob->m_Family == 335)
    {
        SetupMaat(PMob);
    }

    if (PMob->CanStealGil())
    {
        PMob->ResetGilPurse();
    }

    if(PMob->m_Type & MOBTYPE_EVENT || PMob->m_Type & MOBTYPE_FISHED || PMob->m_Type & MOBTYPE_BATTLEFIELD ||
        zoneType == ZONETYPE_BATTLEFIELD || zoneType == ZONETYPE_DYNAMIS)
    {
        PMob->setMobMod(MOBMOD_CHARMABLE, 0);
    }

    // Check for possible miss-setups
    if (PMob->getMobMod(MOBMOD_SPECIAL_SKILL) != 0 && PMob->getMobMod(MOBMOD_SPECIAL_COOL) == 0)
    {
        ShowError("Mobutils::CalculateStats Mob (%s, %d) with special skill but no cool down set!\n", PMob->GetName(), PMob->id);
    }

    if (PMob->SpellContainer->HasSpells() && PMob->getMobMod(MOBMOD_MAGIC_COOL) == 0)
    {
        ShowError("Mobutils::CalculateStats Mob (%s, %d) with magic but no cool down set!\n", PMob->GetName(), PMob->id);
    }

    if (PMob->m_Detects == 0)
    {
        ShowError("Mobutils::CalculateStats Mob (%s, %d, %d) has no detection methods!\n", PMob->GetName(), PMob->id, PMob->m_Family);
    }
}
Exemplo n.º 4
0
void CASW_Weapon_Sniper_Rifle::PrimaryAttack( void )
{
	// If my clip is empty (and I use clips) start reload
	if ( UsesClipsForAmmo1() && !m_iClip1 ) 
	{
		Reload();
		return;
	}

	CASW_Player *pPlayer = GetCommander();
	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine )
		return;

	// MUST call sound before removing a round from the clip of a CMachineGun
	WeaponSound(SINGLE);
	if (m_iClip1 <= AmmoClickPoint())
		BaseClass::WeaponSound( EMPTY );

	m_bIsFiring = true;

	// tell the marine to tell its weapon to draw the muzzle flash
	pMarine->DoMuzzleFlash();

	// sets the animation on the weapon model iteself
	//SendWeaponAnim( GetPrimaryAttackActivity() );

	// sets the animation on the marine holding this weapon
	//pMarine->SetAnimation( PLAYER_ATTACK1 );

#ifdef GAME_DLL	// check for turning on lag compensation
	if (pPlayer && pMarine->IsInhabited())
	{
		CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
	}
#endif

	FireBulletsInfo_t info;
	info.m_vecSrc = pMarine->Weapon_ShootPosition( );
	if ( pPlayer && pMarine->IsInhabited() )
	{
		info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187
	}
	else
	{
#ifdef CLIENT_DLL
		Msg("Error, clientside firing of a weapon that's being controlled by an AI marine\n");
#else
		info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc );
#endif
	}
	
	info.m_iShots = 1;			

	// Make sure we don't fire more than the amount in the clip
	if ( UsesClipsForAmmo1() )
	{
		info.m_iShots = MIN( info.m_iShots, m_iClip1 );
		m_iClip1 -= info.m_iShots;
#ifdef GAME_DLL
		CASW_Marine *pMarine = GetMarine();
		if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
		{
			// check he doesn't have ammo in an ammo bay
			CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0));
			if (!pAmmoBag)
				pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1));
			if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this))
				pMarine->OnWeaponOutOfAmmo(true);
		}
#endif
	}
	else
	{
		info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) );
		pMarine->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
	}

	info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat();
	info.m_iAmmoType = m_iPrimaryAmmoType;
	info.m_iTracerFreq = 1;
	info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat();

	info.m_vecSpread = GetBulletSpread();
	info.m_flDamage = GetWeaponDamage();
#ifndef CLIENT_DLL
	if (asw_debug_marine_damage.GetBool())
		Msg("Weapon dmg = %f\n", info.m_flDamage);
	info.m_flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale();
#endif

	int iPenetration = 1;
	if ( pMarine->GetDamageBuffEndTime() > gpGlobals->curtime )		// sniper rifle penetrates more targets when marine is in a damage amp
	{
		iPenetration = 3;
	}
	pMarine->FirePenetratingBullets( info, iPenetration, 3.5f, 0, true, NULL, false  );

	// increment shooting stats
#ifndef CLIENT_DLL
	if (pMarine && pMarine->GetMarineResource())
	{
		pMarine->GetMarineResource()->UsedWeapon(this, 1);
		pMarine->OnWeaponFired( this, 1 );
	}
#endif
	
	if (m_iClip1 > 0)		// only force the fire wait time if we have ammo for another shot
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
	else
		m_flNextPrimaryAttack = gpGlobals->curtime;
	m_fSlowTime = gpGlobals->curtime + 0.03f;
}
void CASW_Weapon_Shotgun::PrimaryAttack( void )
{
	// If my clip is empty (and I use clips) start reload
	if ( UsesClipsForAmmo1() && !m_iClip1 ) 
	{
		Reload();
		return;
	}

	CASW_Player *pPlayer = GetCommander();
	CASW_Marine *pMarine = GetMarine();

	if (pMarine)		// firing from a marine
	{
		// MUST call sound before removing a round from the clip of a CMachineGun
		WeaponSound(SINGLE);
		if (m_iClip1 <= AmmoClickPoint())
		{
			LowAmmoSound();
		}

		m_bIsFiring = true;

		// tell the marine to tell its weapon to draw the muzzle flash
		pMarine->DoMuzzleFlash();

		// sets the animation on the weapon model iteself
		SendWeaponAnim( GetPrimaryAttackActivity() );

#ifdef GAME_DLL	// check for turning on lag compensation
		if (pPlayer && pMarine->IsInhabited())
		{
			CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
		}
#endif

		Vector vecSrc = pMarine->Weapon_ShootPosition( );
		// hull trace out to this shoot position, so we can be sure we're not firing from over an alien's head
		trace_t tr;
		CTraceFilterSimple tracefilter(pMarine, COLLISION_GROUP_NONE);
		Vector vecMarineMiddle(pMarine->GetAbsOrigin());
		vecMarineMiddle.z = vecSrc.z;
		AI_TraceHull( vecMarineMiddle, vecSrc, Vector( -10, -10, -20 ), Vector( 10, 10, 10 ), MASK_SHOT, &tracefilter, &tr );
		vecSrc = tr.endpos;

		Vector vecAiming = vec3_origin;
		if ( pPlayer && pMarine->IsInhabited() )
		{
			vecAiming = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187
		}
		else
		{
#ifndef CLIENT_DLL
			vecAiming = pMarine->GetActualShootTrajectory( vecSrc );
#endif
		}

		if (true)		// hitscan pellets
		{

#ifndef CLIENT_DLL
			if (asw_DebugAutoAim.GetBool())
			{
				NDebugOverlay::Line(vecSrc, vecSrc + vecAiming * asw_weapon_max_shooting_distance.GetFloat(), 64, 0, 64, false, 120.0);
			}
#endif
			int iPellets = GetNumPellets();
			for (int i=0;i<iPellets;i++)
			{
				FireBulletsInfo_t info( 1, vecSrc, vecAiming, GetAngularBulletSpread(), asw_weapon_max_shooting_distance.GetFloat(), m_iPrimaryAmmoType );
				info.m_pAttacker = pMarine;
				info.m_iTracerFreq = 1;
				info.m_nFlags = FIRE_BULLETS_NO_PIERCING_SPARK | FIRE_BULLETS_HULL | FIRE_BULLETS_ANGULAR_SPREAD;
				info.m_flDamage = GetWeaponDamage();
				info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat();
	#ifndef CLIENT_DLL
				if (asw_debug_marine_damage.GetBool())
					Msg("Weapon dmg = %f\n", info.m_flDamage);
				info.m_flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale();
	#endif
				// shotgun bullets have a base 50% chance of piercing
				//float fPiercingChance = 0.5f;
				//if (pMarine->GetMarineResource() && pMarine->GetMarineProfile() && pMarine->GetMarineProfile()->GetMarineClass() == MARINE_CLASS_SPECIAL_WEAPONS)
					//fPiercingChance += MarineSkills()->GetSkillBasedValueByMarine(pMarine, ASW_MARINE_SKILL_PIERCING);
				
				//pMarine->FirePenetratingBullets(info, 5, fPiercingChance);

				//pMarine->FirePenetratingBullets(info, 5, 1.0f, i, false );
				pMarine->FirePenetratingBullets(info, 0, 1.0f, i, false );
			}
		}
		else	// projectile pellets
		{
#ifndef CLIENT_DLL
			CShotManipulator Manipulator( vecAiming );
					
			int iPellets = GetNumPellets();
			for (int i=0;i<iPellets;i++)
			{
				// create a pellet at some random spread direction
				//CASW_Shotgun_Pellet *pPellet = 			
				Vector newVel = Manipulator.ApplySpread(GetBulletSpread());
				//Vector newVel = ApplySpread( vecAiming, GetBulletSpread() );
				if ( pMarine->GetWaterLevel() == 3 )
					newVel *= PELLET_WATER_VELOCITY;
				else
					newVel *= PELLET_AIR_VELOCITY;
				newVel *= (1.0 + (0.1 * random->RandomFloat(-1,1)));
				CreatePellet(vecSrc, newVel, pMarine);
				
				//CASW_Shotgun_Pellet_Predicted::CreatePellet(vecSrc, newVel, pPlayer, pMarine);
			}
#endif
		}

		// increment shooting stats
#ifndef CLIENT_DLL
		if (pMarine && pMarine->GetMarineResource())
		{
			pMarine->GetMarineResource()->UsedWeapon(this, 1);
			pMarine->OnWeaponFired( this, GetNumPellets() );
		}
#endif

		// decrement ammo
		m_iClip1 -= 1;
#ifdef GAME_DLL
		CASW_Marine *pMarine = GetMarine();
		if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
		{
			// check he doesn't have ammo in an ammo bay
			CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0));
			if (!pAmmoBag)
				pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1));
			if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this))
				pMarine->OnWeaponOutOfAmmo(true);
		}
#endif
	}
	
	if (m_iClip1 > 0)		// only force the fire wait time if we have ammo for another shot
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
	else
		m_flNextPrimaryAttack = gpGlobals->curtime;
	m_fSlowTime = gpGlobals->curtime + 0.1f;
}
Exemplo n.º 6
0
void CalculateStats(CMobEntity * PMob)
{
	// remove all to keep mods in sync
	PMob->StatusEffectContainer->KillAllStatusEffect();
	PMob->restoreModifiers();
	PMob->restoreMobModifiers();

	// set a random job
	if(PMob->getMobMod(MOBMOD_RAND_JOB))
	{
		bool firstOption = WELL512::irand()%2 == 0;
		SKILLTYPE meleeSkill = SKILL_NON;
		JOBTYPE job = JOB_NON;
		uint16 spellList = 0;

		// skeleton
		if(PMob->m_Family == 227)
		{
			if(firstOption)
			{
				// blm
				job = JOB_BLM;
				// taken from mob_pools modelid
				int8 look[23] = {0x00, 0x00, 0x34, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
				memcpy(&PMob->look, look, 23);
				spellList = 28; // undead spell list
				meleeSkill = SKILL_SYH;
			}
			else
			{
				// war
				job = JOB_WAR;
				int8 look[23] = {0x00, 0x00, 0x3C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
				memcpy(&PMob->look, look, 23);
				meleeSkill = SKILL_AXE;
			}
		}
		// evil weapon
		else if(PMob->m_Family == 110 || PMob->m_Family == 111)
		{
			if(firstOption)
			{
				// rdm
				job = JOB_RDM;
				meleeSkill = SKILL_SWD;
				spellList = 42; // evil weapon spell list
			}
			else
			{
				// war
				job = JOB_WAR;
				meleeSkill = SKILL_AXE;
			}
		}
		else
		{
			ShowError("mobutils::CalculateStats Undefined family is being set as a random job %d\n", PMob->m_Family);
		}

		PMob->SetMJob(job);
		PMob->SetSJob(job);
		PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(spellList);
		PMob->m_Weapons[SLOT_MAIN]->setSkillType(meleeSkill);
	}

	bool isNM = PMob->m_Type & MOBTYPE_NOTORIOUS;
	JOBTYPE mJob = PMob->GetMJob();
	JOBTYPE sJob = PMob->GetSJob();
	uint8 mLvl = PMob->GetMLevel();
	ZONETYPE zoneType = PMob->loc.zone->GetType();

	// event mob types will always have custom roaming
	if(PMob->m_Type & MOBTYPE_EVENT)
	{
		PMob->m_roamFlags |= ROAMFLAG_EVENT;
		PMob->m_maxRoamDistance = 0.2f; // always go back to spawn
	}

	if(isNM)
	{
		// enmity range is larger
		PMob->m_enmityRange = 28;
	}

	if(mJob == JOB_DRG)
	{
		// drg can use 2 hour multiple times
		PMob->setMobMod(MOBMOD_2HOUR_MULTI, 1);
	}

	if(PMob->HPmodifier == 0){

		float growth = 1.06;
		float base = 18.0;
		uint8 lvl = PMob->GetMLevel();

		//give hp boost every 10 levels after 25
		//special boosts at 25 and 50
		if(lvl > 75){
			growth = 1.28;
		}else if(lvl > 65){
			growth = 1.27;
		} else if(lvl > 55){
			growth = 1.25;
		} else if(lvl > 50){
			growth = 1.21;
		} else if(lvl > 45){
			growth = 1.17;
		} else if(lvl > 35){
			growth = 1.14;
		} else if(lvl > 25){
			growth = 1.1;
		}

		// pets have lower health
		if(PMob->PMaster != NULL)
		{
			growth = 0.95;
		}


		PMob->health.maxhp = (int16)(base * pow(lvl, growth) * PMob->HPscale);

		if(isNM)
		{
			PMob->health.maxhp *= 2.0;
			if(PMob->GetMLevel() > 75){
				PMob->health.maxhp *= 2.5;
			}
		}

	} else {
		PMob->health.maxhp = PMob->HPmodifier;
	}

	bool hasMp = false;

	switch(mJob){
	case JOB_PLD:
	case JOB_WHM:
	case JOB_BLM:
	case JOB_RDM:
	case JOB_DRK:
	case JOB_BLU:
	case JOB_SCH:
	case JOB_SMN:
		hasMp = true;
		break;
	}

	switch(sJob){
	case JOB_PLD:
	case JOB_WHM:
	case JOB_BLM:
	case JOB_RDM:
	case JOB_DRK:
	case JOB_BLU:
	case JOB_SCH:
	case JOB_SMN:
		hasMp = true;
		break;
	}

	if(PMob->getMobMod(MOBMOD_MP_BASE))
	{
		hasMp = true;
	}

	if(hasMp)
	{
		float scale = PMob->MPscale;

		if(PMob->getMobMod(MOBMOD_MP_BASE))
		{
			scale = (float)PMob->getMobMod(MOBMOD_MP_BASE) / 100.0f;
		}

		if(PMob->MPmodifier == 0){
			PMob->health.maxmp = (int16)(18.2 * pow(PMob->GetMLevel(),1.1075) * scale) + 10;
			if(isNM){
			PMob->health.maxmp *= 1.5;
				if(PMob->GetMLevel()>75){
					PMob->health.maxmp *= 1.5;
				}
			}
		} else {
			PMob->health.maxmp = PMob->MPmodifier;
		}
	}

    PMob->UpdateHealth();

	PMob->health.tp = 0;
    PMob->health.hp = PMob->GetMaxHP();
    PMob->health.mp = PMob->GetMaxMP();

	PMob->m_Weapons[SLOT_MAIN]->setDamage(GetWeaponDamage(PMob));

    //reduce weapon delay of MNK
    if(PMob->GetMJob()==JOB_MNK){
		PMob->m_Weapons[SLOT_MAIN]->resetDelay();
    }

	uint16 fSTR = GetBaseToRank(PMob->strRank, PMob->GetMLevel());
	uint16 fDEX = GetBaseToRank(PMob->dexRank, PMob->GetMLevel());
	uint16 fVIT = GetBaseToRank(PMob->vitRank, PMob->GetMLevel());
	uint16 fAGI = GetBaseToRank(PMob->agiRank, PMob->GetMLevel());
	uint16 fINT = GetBaseToRank(PMob->intRank, PMob->GetMLevel());
	uint16 fMND = GetBaseToRank(PMob->mndRank, PMob->GetMLevel());
	uint16 fCHR = GetBaseToRank(PMob->chrRank, PMob->GetMLevel());

	uint16 mSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),2), PMob->GetMLevel());
	uint16 mDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),3), PMob->GetMLevel());
	uint16 mVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),4), PMob->GetMLevel());
	uint16 mAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),5), PMob->GetMLevel());
	uint16 mINT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),6), PMob->GetMLevel());
	uint16 mMND = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),7), PMob->GetMLevel());
	uint16 mCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),8), PMob->GetMLevel());

	uint16 sSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),2), PMob->GetSLevel());
	uint16 sDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),3), PMob->GetSLevel());
	uint16 sVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),4), PMob->GetSLevel());
	uint16 sAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),5), PMob->GetSLevel());
	uint16 sINT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),6), PMob->GetSLevel());
	uint16 sMND = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),7), PMob->GetSLevel());
	uint16 sCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),8), PMob->GetSLevel());

	if(PMob->GetSLevel() > 15)
	{
		sSTR /= 2;
		sDEX /= 2;
		sAGI /= 2;
		sINT /= 2;
		sMND /= 2;
		sCHR /= 2;
		sVIT /= 2;
	} else {
		sSTR = 0;
		sDEX = 0;
		sAGI = 0;
		sINT = 0;
		sMND = 0;
		sCHR = 0;
		sVIT = 0;
	}

	PMob->stats.STR = fSTR + mSTR + sSTR;
	PMob->stats.DEX = fDEX + mDEX + sDEX;
	PMob->stats.VIT = fVIT + mVIT + sVIT;
	PMob->stats.AGI = fAGI + mAGI + sAGI;
	PMob->stats.INT = fINT + mINT + sINT;
	PMob->stats.MND = fMND + mMND + sMND;
	PMob->stats.CHR = fCHR + mCHR + sCHR;

	if(isNM){
		PMob->stats.STR *= 1.5;
		PMob->stats.DEX *= 1.5;
		PMob->stats.VIT *= 1.5;
		PMob->stats.AGI *= 1.5;
		PMob->stats.INT *= 1.5;
		PMob->stats.MND *= 1.5;
		PMob->stats.CHR *= 1.5;
	}

	// aggro mobs move around a bit more often
	if(PMob->m_Aggro != AGGRO_NONE && PMob->speed != 0)
	{
		PMob->setMobMod(MOBMOD_ROAM_COOL, 20);
	}

	// setup special ability
	if(mJob == JOB_RNG)
	{

		// giga
		if(PMob->m_Family == 126 && PMob->m_Family <= 130)
		{
			PMob->setMobMod(MOBMOD_SPECIAL_COOL, 35);
			// catapult
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 402);
		}
		else
		{
			// all other rangers
			PMob->setMobMod(MOBMOD_SPECIAL_COOL, 20);
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 16);
		}

	}
	else if(mJob == JOB_NIN)
	{
		PMob->setMobMod(MOBMOD_SPECIAL_COOL, 35);
		PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 16);
	}
	else if(mJob == JOB_DRG && PMob->m_Family != 193)
	{
		PMob->setMobMod(MOBMOD_SPECIAL_COOL, 45);

		// sahigans
		if(PMob->m_Family == 213)
		{
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 514);
		}
		else
		{
			// all other dragoons
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 808);
		}
	}

	// all pets must be defined in the mob_pets file
	// set recast times for summoning pets
	if(PMob->loc.zone->GetType() != ZONETYPE_DYNAMIS)
	{
		if(mJob == JOB_BST)
		{
			PMob->setMobMod(MOBMOD_SPECIAL_COOL, 100);
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 761);
		}
		else if(mJob == JOB_DRG && !isNM)
		{
			// only drgs in 3rd expansion calls wyvern as non-NM
			// include fomors
			if(PMob->loc.zone->GetContinentID() == THE_ARADJIAH_CONTINENT || PMob->m_Family == 115)
			{
				// 20 min recast
				PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 476);
				PMob->setMobMod(MOBMOD_SPECIAL_COOL, 720);
			}
		}
		else if(mJob == JOB_PUP)
		{
			PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 1645);
			PMob->setMobMod(MOBMOD_SPECIAL_COOL, 720);
		}
	}

	// ambush antlions
	if(PMob->m_Family == 357)
	{
		PMob->setMobMod(MOBMOD_SPECIAL_SKILL, 22);
		PMob->setMobMod(MOBMOD_SPECIAL_COOL, 1);
		PMob->m_specialFlags |= SPECIALFLAG_HIDDEN;
		PMob->m_roamFlags |= ROAMFLAG_AMBUSH;
	}

    // Phuabo
    if(PMob->m_Family == 194)
    {
        PMob->m_roamFlags |= ROAMFLAG_STEALTH;
    }

    // Yovra
    if(PMob->m_Family == 271)
    {
        PMob->m_roamFlags |= ROAMFLAG_STEALTH;
    }

    // Chigoe
    if(PMob->m_Family == 64)
    {
        PMob->m_roamFlags |= ROAMFLAG_STEALTH;
    }

    // Amphiptere
    if(PMob->m_Family == 6)
    {
       PMob->m_roamFlags |= ROAMFLAG_STEALTH;
    }

	if(PMob->m_Family == 362)
	{
		// rapido doesn't stop
		PMob->m_roamFlags |= ROAMFLAG_IGNORE;
	}


	// handle standback
	// mobs that stand back: blm, whm, rng, cor, nin
	if(mJob == JOB_RNG)
	{

		// giga
		if(PMob->m_Family == 126 && PMob->m_Family <= 130)
		{
			PMob->setMobMod(MOBMOD_STANDBACK_TIME, 20);
		}
		else if(PMob->m_Family == 199)
		{
			// they stay back forever
			PMob->setMobMod(MOBMOD_STANDBACK_TIME, 90);
		}
		else
		{
			PMob->setMobMod(MOBMOD_STANDBACK_TIME, 60);
		}

	}
	else if(mJob == JOB_COR)
	{
		PMob->setMobMod(MOBMOD_STANDBACK_TIME, 60);
	}
	else if(mJob == JOB_BLM)
	{
		PMob->setMobMod(MOBMOD_STANDBACK_TIME, 42);
	}
	else if(mJob == JOB_WHM)
	{
		PMob->setMobMod(MOBMOD_STANDBACK_TIME, 32);
	}
	else if(mJob == JOB_NIN)
	{
		PMob->setMobMod(MOBMOD_STANDBACK_TIME, 25);
	}

	// mobs with zero speed cannot standback
	if(PMob->speed == 0)
	{
		PMob->setMobMod(MOBMOD_STANDBACK_TIME, 0);
	}

    // special case, give spell list to my pet
    if(PMob->getMobMod(MOBMOD_PET_SPELL_LIST) && PMob->PPet != NULL)
    {
    	// Stubborn_Dredvodd
    	CMobEntity* PPet = (CMobEntity*)PMob->PPet;

    	// give pet spell list
    	PPet->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_PET_SPELL_LIST));
    }

    if(PMob->getMobMod(MOBMOD_SPELL_LIST))
    {
    	PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_SPELL_LIST));
    }

	// TODO: this should be put into its own column
	// has not been decided where yet
	if(PMob->m_Family == 258 || PMob->m_Family == 276)
	{
		// makes worms roam by going into ground / back up
		PMob->m_roamFlags |= ROAMFLAG_WORM;
	}

	if(PMob->m_Aggro != AGGRO_NONE && PMob->loc.zone->GetType() == ZONETYPE_OUTDOORS)
	{
		PMob->m_roamFlags |= ROAMFLAG_MEDIUM;
	}
	else
	{
		PMob->m_roamFlags |= ROAMFLAG_SMALL;
	}

	if(PMob->m_roamFlags & ROAMFLAG_AMBUSH)
	{
		// always stay close to spawn
		PMob->m_maxRoamDistance = 2.0f;
	}

	// cap all stats for lvl / job
	for (int i=SKILL_DIV; i <=SKILL_BLU; i++) {
		uint16 maxSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetMJob(),PMob->GetMLevel());
		if (maxSkill != 0) {
			PMob->WorkingSkills.skill[i] = maxSkill;
		}
		else //if the mob is WAR/BLM and can cast spell
		{
			// set skill as high as main level, so their spells won't get resisted
			uint16 maxSubSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetSJob(),PMob->GetMLevel());

			if (maxSubSkill != 0)
			{
				PMob->WorkingSkills.skill[i] = maxSubSkill;
			}
		}
	}

	if(zoneType == ZONETYPE_DYNAMIS || zoneType == ZONETYPE_BATTLEFIELD)
	{
		// never despawn
		PMob->SetDespawnTimer(0);
		// do not roam around
		PMob->m_roamFlags |= ROAMFLAG_EVENT;
		PMob->m_maxRoamDistance = 0.5f;
	}

	if((zoneType == ZONETYPE_BATTLEFIELD) && (PMob->m_bcnmID != 864) && (PMob->m_bcnmID != 704))
	{
		// bcnmID 864 (desires of emptiness) and 704 (darkness named) don't superlink
		// force all mobs in same instance to superlink
		// plus one in case id is zero
		PMob->setMobMod(MOBMOD_SUPERLINK, PMob->m_battlefieldID);
	}

	uint8 evaRank = battleutils::GetSkillRank(SKILL_EVA, PMob->GetMJob());

    PMob->addModifier(MOD_DEF, GetBase(PMob,PMob->defRank));
    PMob->addModifier(MOD_EVA, GetBase(PMob,evaRank));
    PMob->addModifier(MOD_ATT, GetBase(PMob,PMob->attRank));
    PMob->addModifier(MOD_ACC, GetBase(PMob,PMob->accRank));

	SKILLTYPE mEvasionRating = SKILL_ELE;

	if(mLvl > 83)
	{
		mEvasionRating = SKILL_SWD;
	}

	//natural magic evasion
	PMob->addModifier(MOD_MEVA, battleutils::GetMaxSkill(mEvasionRating, JOB_RDM, mLvl));

	if((PMob->m_Type & MOBTYPE_NOTORIOUS) && mJob == JOB_WHM && mLvl >= 25)
	{
		// whm nms have stronger regen effect
		PMob->addModifier(MOD_REGEN, PMob->GetMLevel()/4);
	}

	// add traits for sub and main
	AddTraits(PMob, mJob, mLvl);
	AddTraits(PMob, PMob->GetSJob(), PMob->GetSLevel());
}
Exemplo n.º 7
0
void CASW_Weapon::PrimaryAttack( void )
{
	// If my clip is empty (and I use clips) start reload
	if ( UsesClipsForAmmo1() && !m_iClip1 ) 
	{		
		Reload();
		return;
	}

	CASW_Player *pPlayer = GetCommander();
	CASW_Marine *pMarine = GetMarine();
	if ( !pMarine )
		return;

	m_bIsFiring = true;
	// MUST call sound before removing a round from the clip of a CMachineGun
	WeaponSound(SINGLE);

	if (m_iClip1 <= AmmoClickPoint())
	{
		LowAmmoSound();
	}

	// tell the marine to tell its weapon to draw the muzzle flash
	pMarine->DoMuzzleFlash();

	// sets the animation on the weapon model itself
	SendWeaponAnim( GetPrimaryAttackActivity() );

	// sets the animation on the marine holding this weapon
	//pMarine->SetAnimation( PLAYER_ATTACK1 );

#ifdef GAME_DLL	// check for turning on lag compensation
	if (pPlayer && pMarine->IsInhabited())
	{
		CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
	}
#endif

	FireBulletsInfo_t info;
	info.m_vecSrc = pMarine->Weapon_ShootPosition( );
	if ( pPlayer && pMarine->IsInhabited() )
	{
		info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187
	}
	else
	{
#ifdef CLIENT_DLL
		Msg("Error, clientside firing of a weapon that's being controlled by an AI marine\n");
#else
		info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc );
#endif
	}

	// To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, 
	// especially if the weapon we're firing has a really fast rate of fire.
	info.m_iShots = 0;
	float fireRate = GetFireRate();
	while ( m_flNextPrimaryAttack <= gpGlobals->curtime )
	{
		m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate;
		info.m_iShots++;
		if ( !fireRate )
			break;
	}

	// Make sure we don't fire more than the amount in the clip
	if ( UsesClipsForAmmo1() )
	{
		info.m_iShots = MIN( info.m_iShots, m_iClip1 );
		m_iClip1 -= info.m_iShots;

#ifdef GAME_DLL
		CASW_Marine *pMarine = GetMarine();
		if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
		{
			// check he doesn't have ammo in an ammo bay
			CASW_Weapon_Ammo_Bag* pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(0));
			if (!pAmmoBag)
				pAmmoBag = dynamic_cast<CASW_Weapon_Ammo_Bag*>(pMarine->GetASWWeapon(1));
			if (!pAmmoBag || !pAmmoBag->CanGiveAmmoToWeapon(this))
				pMarine->OnWeaponOutOfAmmo(true);
		}
#endif
	}
	else
	{
		info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) );
		pMarine->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
	}

	info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat();
	info.m_iAmmoType = m_iPrimaryAmmoType;
	info.m_iTracerFreq = 1;  // asw tracer test everytime
	info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat();

	info.m_vecSpread = pMarine->GetActiveWeapon()->GetBulletSpread();
	info.m_flDamage = GetWeaponDamage();
#ifndef CLIENT_DLL
	if (asw_debug_marine_damage.GetBool())
		Msg("Weapon dmg = %f\n", info.m_flDamage);
	info.m_flDamage *= pMarine->GetMarineResource()->OnFired_GetDamageScale();
	if (asw_DebugAutoAim.GetBool())
	{
		NDebugOverlay::Line(info.m_vecSrc, info.m_vecSrc + info.m_vecDirShooting * info.m_flDistance, 64, 0, 64, true, 1.0);
	}
#endif

	pMarine->FireBullets( info );

	// increment shooting stats
#ifndef CLIENT_DLL
	if (pMarine && pMarine->GetMarineResource())
	{
		pMarine->GetMarineResource()->UsedWeapon(this, info.m_iShots);
		pMarine->OnWeaponFired( this, info.m_iShots );
	}
#endif
}
void CASW_Weapon_Pistol::PrimaryAttack( void )
{
	// If my clip is empty (and I use clips) start reload
	if ( UsesClipsForAmmo1() && !m_iClip1 ) 
	{
		Reload();
		return;
	}

	CASW_Player *pPlayer = GetCommander();
	CASW_Marine *pMarine = GetMarine();

	if (pMarine)		// firing from a marine
	{
		// MUST call sound before removing a round from the clip of a CMachineGun
		WeaponSound(SINGLE);
		if (m_iClip1 <= AmmoClickPoint())
			BaseClass::WeaponSound( EMPTY );

		m_bIsFiring = true;

		// tell the marine to tell its weapon to draw the muzzle flash
		pMarine->DoMuzzleFlash();

		// sets the animation on the weapon model iteself
		SendWeaponAnim( GetPrimaryAttackActivity() );

		// sets the animation on the marine holding this weapon
		//pMarine->SetAnimation( PLAYER_ATTACK1 );

#ifdef GAME_DLL	// check for turning on lag compensation
		if (pPlayer && pMarine->IsInhabited())
		{
			CASW_Lag_Compensation::RequestLagCompensation( pPlayer, pPlayer->GetCurrentUserCommand() );
		}
#endif

		//	if (asw_pistol_hitscan.GetBool())
		if (true)
		{
			FireBulletsInfo_t info;
			info.m_vecSrc = pMarine->Weapon_ShootPosition( );
			if ( pPlayer && pMarine->IsInhabited() )
			{
				info.m_vecDirShooting = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187
			}
			else
			{
#ifdef CLIENT_DLL
				Msg("Error, clientside firing of a weapon that's being controlled by an AI marine\n");
#else
				info.m_vecDirShooting = pMarine->GetActualShootTrajectory( info.m_vecSrc );
#endif
			}
			
			info.m_iShots = 1;			

			// Make sure we don't fire more than the amount in the clip
			if ( UsesClipsForAmmo1() )
			{
				info.m_iShots = MIN( info.m_iShots, m_iClip1 );
				m_iClip1 -= info.m_iShots;
#ifdef GAME_DLL
				CASW_Marine *pMarine = GetMarine();
				if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
				{
					pMarine->OnWeaponOutOfAmmo(true);
				}
#endif
			}
			else
			{
				info.m_iShots = MIN( info.m_iShots, pMarine->GetAmmoCount( m_iPrimaryAmmoType ) );
				pMarine->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType );
			}

			info.m_flDistance = asw_weapon_max_shooting_distance.GetFloat();
			info.m_iAmmoType = m_iPrimaryAmmoType;
			info.m_iTracerFreq = 1;
			info.m_flDamageForceScale = asw_weapon_force_scale.GetFloat();
		
			info.m_vecSpread = GetBulletSpread();
			info.m_flDamage = GetWeaponDamage();
#ifndef CLIENT_DLL
			if (asw_debug_marine_damage.GetBool())
				Msg("Weapon dmg = %f\n", info.m_flDamage);
			info.m_flDamage *= pMarine->OnFired_GetDamageScale();
#endif

			pMarine->FireBullets( info );

			//FireBulletsInfo_t info( 1, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType );
			//info.m_pAttacker = pMarine;

			// Fire the bullets, and force the first shot to be perfectly accuracy
			//pMarine->FireBullets( info );
		}
		else	// projectile pistol
		{
		
#ifndef CLIENT_DLL
			Vector vecSrc = pMarine->Weapon_ShootPosition( );
			Vector vecAiming = vec3_origin;
			if ( pPlayer && pMarine->IsInhabited() )
			{
				vecAiming = pPlayer->GetAutoaimVectorForMarine(pMarine, GetAutoAimAmount(), GetVerticalAdjustOnlyAutoAimAmount());	// 45 degrees = 0.707106781187
			}
			else
			{
				vecAiming = pMarine->GetActualShootTrajectory( vecSrc );
			}

			CShotManipulator Manipulator( vecAiming );
			AngularImpulse rotSpeed(0,0,720);
					
			Vector newVel = Manipulator.ApplySpread(GetBulletSpread());
			if ( pMarine->GetWaterLevel() == 3 )
				newVel *= PELLET_WATER_VELOCITY;
			else
				newVel *= PELLET_AIR_VELOCITY;
			newVel *= (1.0 + (0.1 * random->RandomFloat(-1,1)));
			CASW_Shotgun_Pellet::Shotgun_Pellet_Create( vecSrc, QAngle(0,0,0),
					newVel, rotSpeed, pMarine, GetWeaponDamage() );

			// decrement ammo
			m_iClip1 -= 1;
			CASW_Marine *pMarine = GetMarine();
			if (pMarine && m_iClip1 <= 0 && pMarine->GetAmmoCount(m_iPrimaryAmmoType) <= 0 )
			{
				pMarine->OnWeaponOutOfAmmo(true);
			}
#endif
		}

		// increment shooting stats
#ifndef CLIENT_DLL
		if (pMarine && pMarine->GetMarineResource())
		{
			pMarine->GetMarineResource()->UsedWeapon(this, 1);
			pMarine->OnWeaponFired( this, 1 );
		}
#endif		
	}
	
	if (m_iClip1 > 0)		// only force the fire wait time if we have ammo for another shot
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
	else
		m_flNextPrimaryAttack = gpGlobals->curtime;
	m_fSlowTime = gpGlobals->curtime + 0.03f;

	if ( m_currentPistol == ASW_WEAPON_PISTOL_LEFT )
	{
		m_currentPistol = ASW_WEAPON_PISTOL_RIGHT;
	}
	else
	{
		m_currentPistol = ASW_WEAPON_PISTOL_LEFT;
	}
}
Exemplo n.º 9
0
void CalculateStats(CMobEntity * PMob)
{
    // remove all to keep mods in sync
    PMob->StatusEffectContainer->KillAllStatusEffect();
    PMob->restoreModifiers();
    PMob->restoreMobModifiers();

    bool isNM = PMob->m_Type & MOBTYPE_NOTORIOUS;
    JOBTYPE mJob = PMob->GetMJob();
    JOBTYPE sJob = PMob->GetSJob();
    uint8 mLvl = PMob->GetMLevel();
    ZONETYPE zoneType = PMob->loc.zone->GetType();

    if(PMob->HPmodifier == 0)
    {
        float hpScale = PMob->HPscale;

        if (PMob->getMobMod(MOBMOD_HP_SCALE) != 0)
        {
            hpScale = (float)PMob->getMobMod(MOBMOD_HP_SCALE) / 100.0f;
        }

        float growth = 1.06;
        float petGrowth = 0.75;
        float base = 18.0;

        //give hp boost every 10 levels after 25
        //special boosts at 25 and 50
        if(mLvl > 75)
        {
            growth = 1.28;
            petGrowth = 1.03;
        }
        else if(mLvl > 65)
        {
            growth = 1.27;
            petGrowth = 1.02;
        }
        else if(mLvl > 55)
        {
            growth = 1.25;
            petGrowth = 0.99;
        }
        else if(mLvl > 50)
        {
            growth = 1.21;
            petGrowth = 0.96;
        }
        else if(mLvl > 45)
        {
            growth = 1.17;
            petGrowth = 0.95;
        }
        else if(mLvl > 35)
        {
            growth = 1.14;
            petGrowth = 0.92;
        }
        else if(mLvl > 25)
        {
            growth = 1.1;
            petGrowth = 0.82;
        }

        // pets have lower health
        if(PMob->PMaster != nullptr)
        {
            growth = petGrowth;
        }


        PMob->health.maxhp = (int16)(base * pow(mLvl, growth) * hpScale);

        if(isNM)
        {
            PMob->health.maxhp *= 2.0;
            if(mLvl > 75){
                PMob->health.maxhp *= 2.5;
            }
        }

    }
    else
    {
        PMob->health.maxhp = PMob->HPmodifier;
    }

    if(isNM)
    {
        PMob->health.maxhp *= map_config.nm_hp_multiplier;
    }
    else
    {
        PMob->health.maxhp *= map_config.mob_hp_multiplier;
    }

    bool hasMp = false;

    switch(mJob){
    case JOB_PLD:
    case JOB_WHM:
    case JOB_BLM:
    case JOB_RDM:
    case JOB_DRK:
    case JOB_BLU:
    case JOB_SCH:
    case JOB_SMN:
        hasMp = true;
        break;
    }

    switch(sJob){
    case JOB_PLD:
    case JOB_WHM:
    case JOB_BLM:
    case JOB_RDM:
    case JOB_DRK:
    case JOB_BLU:
    case JOB_SCH:
    case JOB_SMN:
        hasMp = true;
        break;
    }

    if(PMob->getMobMod(MOBMOD_MP_BASE))
    {
        hasMp = true;
    }

    if(hasMp)
    {
        float scale = PMob->MPscale;

        if(PMob->getMobMod(MOBMOD_MP_BASE))
        {
            scale = (float)PMob->getMobMod(MOBMOD_MP_BASE) / 100.0f;
        }

        if(PMob->MPmodifier == 0)
        {
            PMob->health.maxmp = (int16)(18.2 * pow(mLvl,1.1075) * scale) + 10;
            if(isNM)
            {
                PMob->health.maxmp *= 1.5;
                if(mLvl>75)
                {
                    PMob->health.maxmp *= 1.5;
                }
            }
        }
        else
        {
            PMob->health.maxmp = PMob->MPmodifier;
        }

        if(isNM)
        {
            PMob->health.maxhp *= map_config.nm_mp_multiplier;
        }
        else
        {
            PMob->health.maxhp *= map_config.mob_mp_multiplier;
        }
    }

    PMob->UpdateHealth();

    PMob->health.tp = 0;
    PMob->health.hp = PMob->GetMaxHP();
    PMob->health.mp = PMob->GetMaxMP();

    PMob->m_Weapons[SLOT_MAIN]->setDamage(GetWeaponDamage(PMob));

    //reduce weapon delay of MNK
    if(PMob->GetMJob()==JOB_MNK){
        PMob->m_Weapons[SLOT_MAIN]->resetDelay();
    }

    uint16 fSTR = GetBaseToRank(PMob->strRank, mLvl);
    uint16 fDEX = GetBaseToRank(PMob->dexRank, mLvl);
    uint16 fVIT = GetBaseToRank(PMob->vitRank, mLvl);
    uint16 fAGI = GetBaseToRank(PMob->agiRank, mLvl);
    uint16 fINT = GetBaseToRank(PMob->intRank, mLvl);
    uint16 fMND = GetBaseToRank(PMob->mndRank, mLvl);
    uint16 fCHR = GetBaseToRank(PMob->chrRank, mLvl);

    uint16 mSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),2), mLvl);
    uint16 mDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),3), mLvl);
    uint16 mVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),4), mLvl);
    uint16 mAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),5), mLvl);
    uint16 mINT = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),6), mLvl);
    uint16 mMND = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),7), mLvl);
    uint16 mCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetMJob(),8), mLvl);

    uint16 sSTR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),2), PMob->GetSLevel());
    uint16 sDEX = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),3), PMob->GetSLevel());
    uint16 sVIT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),4), PMob->GetSLevel());
    uint16 sAGI = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),5), PMob->GetSLevel());
    uint16 sINT = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),6), PMob->GetSLevel());
    uint16 sMND = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),7), PMob->GetSLevel());
    uint16 sCHR = GetBaseToRank(grade::GetJobGrade(PMob->GetSJob(),8), PMob->GetSLevel());

    if(PMob->GetSLevel() > 15)
    {
        sSTR /= 2;
        sDEX /= 2;
        sAGI /= 2;
        sINT /= 2;
        sMND /= 2;
        sCHR /= 2;
        sVIT /= 2;
    }
    else
    {
        sSTR = 0;
        sDEX = 0;
        sAGI = 0;
        sINT = 0;
        sMND = 0;
        sCHR = 0;
        sVIT = 0;
    }

    PMob->stats.STR = fSTR + mSTR + sSTR;
    PMob->stats.DEX = fDEX + mDEX + sDEX;
    PMob->stats.VIT = fVIT + mVIT + sVIT;
    PMob->stats.AGI = fAGI + mAGI + sAGI;
    PMob->stats.INT = fINT + mINT + sINT;
    PMob->stats.MND = fMND + mMND + sMND;
    PMob->stats.CHR = fCHR + mCHR + sCHR;

    if(isNM)
    {
        PMob->stats.STR *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.DEX *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.VIT *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.AGI *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.INT *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.MND *= (1.5 * map_config.nm_stat_multiplier);
        PMob->stats.CHR *= (1.5 * map_config.nm_stat_multiplier);
    }
    else
    {
        PMob->stats.STR *= map_config.mob_stat_multiplier;
        PMob->stats.DEX *= map_config.mob_stat_multiplier;
        PMob->stats.VIT *= map_config.mob_stat_multiplier;
        PMob->stats.AGI *= map_config.mob_stat_multiplier;
        PMob->stats.INT *= map_config.mob_stat_multiplier;
        PMob->stats.MND *= map_config.mob_stat_multiplier;
        PMob->stats.CHR *= map_config.mob_stat_multiplier;
    }

    // special case, give spell list to my pet
    if(PMob->getMobMod(MOBMOD_PET_SPELL_LIST) && PMob->PPet != nullptr)
    {
        // Stubborn_Dredvodd
        CMobEntity* PPet = (CMobEntity*)PMob->PPet;

        // give pet spell list
        PPet->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_PET_SPELL_LIST));
    }

    if(PMob->getMobMod(MOBMOD_SPELL_LIST))
    {
        PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(PMob->getMobMod(MOBMOD_SPELL_LIST));
    }

    // cap all stats for mLvl / job
    for (int i=SKILL_DIV; i <=SKILL_BLU; i++)
    {
        uint16 maxSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetMJob(),mLvl > 99 ? 99 : mLvl);
        if (maxSkill != 0)
            {
            PMob->WorkingSkills.skill[i] = maxSkill;
        }
        else //if the mob is WAR/BLM and can cast spell
        {
            // set skill as high as main level, so their spells won't get resisted
            uint16 maxSubSkill = battleutils::GetMaxSkill((SKILLTYPE)i,PMob->GetSJob(),mLvl > 99 ? 99 : mLvl);

            if (maxSubSkill != 0)
            {
                PMob->WorkingSkills.skill[i] = maxSubSkill;
            }
        }
    }

    PMob->addModifier(MOD_DEF, GetBase(PMob,PMob->defRank));
    PMob->addModifier(MOD_EVA, GetEvasion(PMob));
    PMob->addModifier(MOD_ATT, GetBase(PMob,PMob->attRank));
    PMob->addModifier(MOD_ACC, GetBase(PMob,PMob->accRank));

    //natural magic evasion
    PMob->addModifier(MOD_MEVA, GetMagicEvasion(PMob));

    // add traits for sub and main
    battleutils::AddTraits(PMob, traits::GetTraits(mJob), mLvl);
    battleutils::AddTraits(PMob, traits::GetTraits(PMob->GetSJob()), PMob->GetSLevel());

    SetupJob(PMob);
    SetupRoaming(PMob);

    if (PMob->PMaster != nullptr)
    {
        SetupPetSkills(PMob);
    }

    PMob->m_Behaviour |= PMob->getMobMod(MOBMOD_BEHAVIOR);

    if(zoneType == ZONETYPE_DUNGEON)
    {
        SetupDungeonMob(PMob);
    }
    else if(zoneType == ZONETYPE_BATTLEFIELD)
    {
        SetupBattlefieldMob(PMob);
    }
    else if(zoneType == ZONETYPE_DYNAMIS)
    {
        SetupDynamisMob(PMob);
    }

    if(PMob->m_Type & MOBTYPE_NOTORIOUS)
    {
        SetupNMMob(PMob);
    }

    if(PMob->m_Type & MOBTYPE_EVENT)
    {
        SetupEventMob(PMob);
    }

    if(PMob->m_Family == 335)
    {
        SetupMaat(PMob);
    }
}