Пример #1
0
void SabBeh_AttackVsBlock( gentity_t *attacker, sabmech_t *mechAttacker, 
								gentity_t *blocker, sabmech_t *mechBlocker, vec3_t hitLoc, qboolean hitSaberBlade,
								qboolean *attackerMishap, qboolean *blockerMishap)
{//set the saber behavior for an attacking vs blocking/parrying blade impact
	qboolean startSaberLock = qfalse;
	qboolean parried = G_BlockIsParry(blocker, attacker, hitLoc);
	
	qboolean atkparry = G_InAttackParry(blocker);
	qboolean atkfake = (attacker->client->ps.userInt3 & (1 << FLAG_ATTACKFAKE)) 
		? qtrue : qfalse;

	G_BlockIsQuickParry(blocker,attacker,hitLoc);//Return value was never used, so I just call it now
	if(parried && blocker->r.svFlags & SVF_BOT 
		&& BOT_ATTACKPARRYRATE * botstates[blocker->s.number]->settings.skill > Q_irand(0,999))
	{//bot performed an attack parry (by cheating a bit)
		//G_Printf("%i: %i: Bot Cheat Attack Parried\n", level.time, blocker->s.number);
		atkparry = qtrue;
	}

	/*
	if(parried && atkparry)
	{
		G_Printf("%i: %i: Attack Parried\n", level.time, blocker->s.number);
	}
	*/

	if(BG_SuperBreakWinAnim(attacker->client->ps.torsoAnim))
	{//attacker was attempting a superbreak and he hit someone who could block the move, rail him for screwing up.
		*attackerMishap = SabBeh_RollBalance(attacker, mechAttacker, qtrue,qfalse);
		SabBeh_AddBalance(attacker, mechAttacker, 2, qtrue);
#ifdef _DEBUG
			mechAttacker->behaveMode = SABBEHAVE_ATTACKPARRIED;
#endif

		SabBeh_AddBalance(blocker, mechBlocker, -1, qfalse);
#ifdef _DEBUG
			mechBlocker->behaveMode = SABBEHAVE_BLOCK;
#endif
	}
	else if(atkfake)
	{//attacker faked before making this attack, treat like standard attack/attack
		if(parried)
		{//defender parried the attack fake.
			*attackerMishap = SabBeh_RollBalance(attacker, mechAttacker, atkparry,qtrue);
			SabBeh_AddBalance(attacker, mechAttacker, MPCOST_PARRIED_ATTACKFAKE, qtrue);
#ifdef _DEBUG
			mechAttacker->behaveMode = SABBEHAVE_ATTACK;
#endif
			if (blocker->client->pers.cmd.buttons & BUTTON_15
				&& blocker->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] >= FORCE_LEVEL_2)
			{
				attacker->client->ps.userInt3 |= (1 << FLAG_QUICKPARRY);
			}
			else
			{
			attacker->client->ps.userInt3 |= ( 1 << FLAG_PARRIED );
			}

			SabBeh_AddBalance(blocker, mechBlocker, MPCOST_PARRYING_ATTACKFAKE, qfalse);
#ifdef _DEBUG
			mechBlocker->behaveMode = SABBEHAVE_BLOCK;
#endif
		}
		else if(atkparry)
		{
			saberKnockOutOfHand(&g_entities[attacker->client->ps.saberEntityNum], attacker, vec3_origin);
		}
		else
		{//otherwise, the defender stands a good chance of having his defensives broken.	
			SabBeh_AddBalance(attacker, mechAttacker, -1, qtrue);

			if(attacker->client->ps.fd.saberAnimLevel == SS_DESANN)
				SabBeh_AddBalance(blocker, mechBlocker, 2, qfalse);

#ifdef _DEBUG
			mechAttacker->behaveMode = SABBEHAVE_ATTACK;
#endif
			if (WP_SabersCheckLock(attacker, blocker))
			{	
				attacker->client->ps.userInt3 |= ( 1 << FLAG_LOCKWINNER );
				attacker->client->ps.saberBlocked = BLOCKED_NONE;
				blocker->client->ps.saberBlocked = BLOCKED_NONE;
				startSaberLock = qtrue;
			}
			
#ifdef _DEBUG
			mechBlocker->behaveMode = SABBEHAVE_BLOCKFAKED;
#endif
		}

	}
	else if(hitSaberBlade && BG_InSlowBounce(&blocker->client->ps) 
		&& blocker->client->ps.userInt3 & (1 << FLAG_OLDSLOWBOUNCE)
		&& attacker->client->ps.fd.saberAnimLevel == SS_TAVION)
	{//blocker's saber was directly hit while in a slow bounce, disarm the blocker!
		mechBlocker->doButterFingers = qtrue;
		blocker->client->ps.saberAttackChainCount = 0;
#ifdef _DEBUG
		mechBlocker->behaveMode = SABBEHAVE_BLOCKFAKED;
#endif

		//set attacker
		SabBeh_AddBalance(attacker, mechAttacker, -3, qtrue);
#ifdef _DEBUG
		mechAttacker->behaveMode = SABBEHAVE_ATTACK;
#endif
	}
	else
	{//standard attack
		//set blocker
#ifdef _DEBUG
		mechBlocker->behaveMode = SABBEHAVE_BLOCK;
#endif

		//set attacker
		if(parried)
		{
		//parry values
			if(attacker->client->ps.saberMove == LS_A_LUNGE
			|| attacker->client->ps.saberMove == LS_SPINATTACK
			|| attacker->client->ps.saberMove == LS_SPINATTACK_DUAL)
			{//attacker's lunge was parried, force mishap.
				*attackerMishap = SabBeh_RollBalance(attacker, mechAttacker, qtrue,atkparry);
			}
			else
			{
				*attackerMishap = SabBeh_RollBalance(attacker, mechAttacker, atkparry,atkparry);
			}
			SabBeh_AddBalance(attacker, mechAttacker, MPCOST_PARRIED, qtrue);
#ifdef _DEBUG
			mechAttacker->behaveMode = SABBEHAVE_ATTACKPARRIED;
#endif
			//[QuickParry]
			if (blocker->client->pers.cmd.buttons & BUTTON_15
				&& blocker->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE] >= FORCE_LEVEL_2)
			{
				attacker->client->ps.userInt3 |= ( 1 << FLAG_QUICKPARRY);
			}
			else
			{
			attacker->client->ps.userInt3 |= ( 1 << FLAG_PARRIED );
			}
			//[/QuickParry]

			SabBeh_AddBalance(blocker, mechBlocker, MPCOST_PARRYING, qfalse);
			
		}
		else
		{//blocked values
			SabBeh_AddBalance(attacker, mechAttacker, -1, qtrue);
			if(attacker->client->ps.fd.saberAnimLevel == SS_TAVION)
			{//aqua styles deals MP to players that don't parry it.
				SabBeh_AddBalance(blocker, mechBlocker, 2, qfalse);
			}
			else if(attacker->client->ps.fd.saberAnimLevel == SS_STRONG)
			{
				blocker->client->ps.fd.forcePower -= 2;
			}
			else if(attacker->client->ps.fd.saberAnimLevel==SS_TAVION
				&& attacker->client->skillLevel[SK_GREENSTYLE] == FORCE_LEVEL_3
				&& (attacker->client->ps.userInt3 & FLAG_QUICKPARRY))
			{
				SabBeh_AddBalance(blocker, mechBlocker, 2, qfalse);
			}
			
#ifdef _DEBUG
			mechAttacker->behaveMode = SABBEHAVE_ATTACKBLOCKED;
#endif

			//SabBeh_AddBalance(blocker, 1, qfalse);
		}
	}

	if(!OnSameTeam(attacker, blocker) || g_friendlySaber.integer)
	{//don't do parries or charge/regen DP unless we're in a situation where we can actually hurt the target.
		if(parried)
		{//parries don't cost any DP and they have a special animation
			//qboolean regenSound = qfalse;
			mechBlocker->doParry = qtrue;
		}
		else if(!startSaberLock)
		{//normal saber blocks
			//update the blocker's block move
			blocker->client->ps.saberLockFrame = 0; //break out of saberlocks.
			WP_SaberBlockNonRandom(blocker, hitLoc, qfalse);
		}
	}

	//do saber DP cost.

	/*
	// debugger message.
	G_Printf("%i: %i: Saber Block Cost: %i atk: %s %s blk: %s %s\n", level.time, blocker->s.number, OJP_SaberBlockCost(blocker, attacker, hitLoc), 
		GetStringForID( animTable, attacker->client->ps.torsoAnim ), GetStringForID( SaberMoveTable, attacker->client->ps.saberMove ), 
		GetStringForID( animTable, blocker->client->ps.torsoAnim ), GetStringForID( SaberMoveTable, blocker->client->ps.saberMove ) );
	*/

	//[ExpSys] -- [DUALRAWR]
	G_DodgeDrain(blocker, attacker, OJP_SaberBlockCost(blocker, attacker, hitLoc));
	//[/ExpSys]

	//costs FP as well.
	BG_AddFatigue(&blocker->client->ps, 1);
}
Пример #2
0
//G_Printf("%i: Bounced Bolt @ Level %i\n", player->s.number, otherDefLevel);
void OJP_HandleBoltBlock(gentity_t *bolt, gentity_t *player, trace_t *trace)
{   //handles all the behavior needed to saber block a blaster bolt.
    //I created this function to unite the duplicated code in G_MissileImpact
    vec3_t fwd;
    gentity_t *saberBoltEffect;
    int otherDefLevel=ReflectionLevel(player);
    int randMax = 0;
    gentity_t *prevOwner = &g_entities[bolt->r.ownerNum]; //previous owner of the bolt.  Used for awarding experience to attacker.
    qboolean manualDeflect = ((player->client->pers.cmd.buttons & BUTTON_ATTACK) ? qtrue : qfalse);
    //create the bolt saber block effect
    saberBoltEffect = G_TempEntity( bolt->r.currentOrigin, EV_SABER_BLOCK );
    VectorCopy(bolt->r.currentOrigin, saberBoltEffect->s.origin);
    VectorCopy(trace->plane.normal, saberBoltEffect->s.angles);
    saberBoltEffect->s.eventParm = 0;
    saberBoltEffect->s.weapon = 0;//saberNum
    saberBoltEffect->s.legsAnim = 0;//bladeNum


    if(manualDeflect)
    {
        if(otherDefLevel == FORCE_LEVEL_3)
        {   //manual reflection, bounce to the crosshair, roughly
            int rand = Q_irand(1,100);
            rand = ( rand <= 50 ? player->client->shotsBlocked+1 : 9001 );
        }
        else if(otherDefLevel == FORCE_LEVEL_2)
        {   //natural reflection, bounce back to the attacker.
            int rand = Q_irand(1,100);
            if(rand <= 25)
            {
                randMax=player->client->shotsBlocked+1;
            }
            else
                randMax=9001;
        }
        else
        {   //just deflect the attack
            int rand = Q_irand(1,100);
            if(rand <= 15)
            {
                randMax=player->client->shotsBlocked+1;
            }
            else
                randMax=9001;
        }
    }
    else
    {
        //determine reflection level.
        if(otherDefLevel == FORCE_LEVEL_3)
        {   //manual reflection, bounce to the crosshair, roughly
            randMax=2;
        }
        else if(otherDefLevel == FORCE_LEVEL_2)
        {   //natural reflection, bounce back to the attacker.
            randMax=5;
        }
        else
        {   //just deflect the attack
            randMax=7;
        }
    }

    //G_Printf("%i: Bounced Bolt @ Level %i\n", player->s.number, otherDefLevel);

    AngleVectors(player->client->ps.viewangles, fwd, NULL, NULL);

    player->client->shotsBlocked++;

    if(player->client->shotsBlocked >= randMax
            && player->client->ps.fd.saberAnimLevel != SS_MEDIUM
            && player->client->ps.fd.saberAnimLevel != SS_TAVION
            && player->client->ps.fd.saberAnimLevel != SS_FAST)
    {

        gentity_t *owner = &g_entities[player->r.ownerNum];
        float distance = VectorDistance(owner->r.currentOrigin, prevOwner->r.currentOrigin);
        player->client->shotsBlocked=0;

        if(distance < 80.0f)
        {   //attempted upclose exception
            G_DeflectMissile(player, bolt, fwd);
        }
        else
        {
            vec3_t	bounce_dir, angs;
            float	speed;
            int i=0;
            //gentity_t	*owner = ent;
            //int		isowner = 0;
            if(!manualDeflect)
            {
                for(i=0; i<3; i++)
                {
                    fwd[i]=1.5f;
                }
            }
            //add some slop factor to the manual reflections.
            if(player->client->pers.cmd.forwardmove >= 0)
            {
                float slopFactor = (MISHAP_MAXINACCURACY-6) * (FORCE_LEVEL_3 - player->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE])/FORCE_LEVEL_3;
                //[MoreRandom]
                slopFactor += Q_irand(1,5);
                vectoangles( fwd, angs );
                //angs[PITCH] += flrand(-slopFactor, slopFactor);
                //angs[YAW] += flrand(-slopFactor, slopFactor);
                angs[PITCH] += flrand(1, slopFactor);
                angs[YAW] += flrand(1, slopFactor);
                AngleVectors( angs, fwd, NULL, NULL );
            }
            else
            {
                vectoangles( fwd, angs );
                angs[PITCH]+=flrand(1,3);
                angs[YAW]+=flrand(1,3);
                AngleVectors( angs, fwd, NULL, NULL );
            }

            //G_Printf("%i: %i: Level 3 Reflect\n", level.time, player->s.number);

            //save the original speed
            speed = VectorNormalize( bolt->s.pos.trDelta );

            VectorCopy(fwd, bounce_dir);

            VectorScale( bounce_dir, speed, bolt->s.pos.trDelta );
            bolt->s.pos.trTime = level.time;		// move a bit on the very first frame
            VectorCopy( bolt->r.currentOrigin, bolt->s.pos.trBase );
            if ( bolt->s.weapon != WP_SABER && bolt->s.weapon != G2_MODEL_PART )
            {   //you are mine, now!
                bolt->r.ownerNum = player->s.number;
            }
            if ( bolt->s.weapon == WP_ROCKET_LAUNCHER )
            {   //stop homing
                bolt->think = 0;
                bolt->nextthink = 0;
            }
        }
    }
    else
        G_DeflectMissile(player, bolt, fwd);
    /*
    	if (otherDefLevel <= FORCE_LEVEL_1)
    	{//only randomly deflect away the bolt
    		G_DeflectMissile(player, bolt, fwd);
    	}
    	else if (otherDefLevel == FORCE_LEVEL_2)
    	{//bounce the bolt back to sender
    		//G_Printf("%i: %i: Level 2 Reflect\n", level.time, player->s.number);
    		G_DeflectMissile(player, bolt, fwd);
    	}
    	else if(otherDefLevel == FORCE_LEVEL_3
    		&& distance < 80.0f
    		&&(BG_SaberInAttack( player->client->ps.saberMove )
    		|| PM_SaberInStart( player->client->ps.saberMove)))
    		{//manual reflection, bounce to the crosshair, roughly
    			G_DeflectMissile(player, bolt, fwd);;
    		}
    	else if(player->client->ps.fd.saberAnimLevel == SS_FAST
    		|| player->client->ps.fd.saberAnimLevel == SS_MEDIUM
    		|| player->client->ps.fd.saberAnimLevel == SS_TAVION)
    	{
    		G_DeflectMissile(player, bolt, fwd);
    	}
    	else
    	{//FORCE_LEVEL_3, reflect the bolt to whereever the player is aiming.
    		gentity_t *owner = &g_entities[player->r.ownerNum];
    		float distance = VectorDistance(owner->r.currentOrigin, prevOwner->r.currentOrigin);
    		if(distance < 80.0f)
    		{//attempted upclose exception
    			G_DeflectMissile(player, bolt, fwd);
    		}
    		else
    		{
    			vec3_t	bounce_dir, angs;
    			float	speed;
    			//gentity_t	*owner = ent;
    			//int		isowner = 0;

    			//add some slop factor to the manual reflections.
    			if(player->client->pers.cmd.forwardmove >= 0)
    			{
    				float slopFactor = (MISHAP_MAXINACCURACY-6) * (FORCE_LEVEL_3 - player->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE])/FORCE_LEVEL_3;
    				//[MoreRandom]
    				float distance = VectorDistance(player->r.currentOrigin,prevOwner->r.currentOrigin);
    					slopFactor += Q_irand(1,5);
    				vectoangles( fwd, angs );
    				//angs[PITCH] += flrand(-slopFactor, slopFactor);
    				//angs[YAW] += flrand(-slopFactor, slopFactor);
    				angs[PITCH] += flrand(1, slopFactor);
    				angs[YAW] += flrand(1, slopFactor);
    				AngleVectors( angs, fwd, NULL, NULL );
    			}
    			else
    			{
    				vectoangles( fwd, angs );
    				angs[PITCH]+=flrand(1,3);
    				angs[YAW]+=flrand(1,3);
    				AngleVectors( angs, fwd, NULL, NULL );
    			}

    			//G_Printf("%i: %i: Level 3 Reflect\n", level.time, player->s.number);

    			//save the original speed
    			speed = VectorNormalize( bolt->s.pos.trDelta );

    			VectorCopy(fwd, bounce_dir);

    			VectorScale( bounce_dir, speed, bolt->s.pos.trDelta );
    			bolt->s.pos.trTime = level.time;		// move a bit on the very first frame
    			VectorCopy( bolt->r.currentOrigin, bolt->s.pos.trBase );
    			if ( bolt->s.weapon != WP_SABER && bolt->s.weapon != G2_MODEL_PART )
    			{//you are mine, now!
    				bolt->r.ownerNum = player->s.number;
    			}
    			if ( bolt->s.weapon == WP_ROCKET_LAUNCHER )
    			{//stop homing
    				bolt->think = 0;
    				bolt->nextthink = 0;
    			}
    		}

    	}
    	*/
    //For jedi AI
    player->client->ps.saberEventFlags |= SEF_DEFLECTED;

    //deduce DP cost
    //[ExpSys]
    bolt->activator = prevOwner;

    if(otherDefLevel == FORCE_LEVEL_3
            && player->client->pers.cmd.forwardmove < 0)
    {
        int amount = OJP_SaberBlockCost(player, bolt, trace->endpos);
        amount/=100*40;
        G_DodgeDrain(player, prevOwner, amount);
    }
    else
        G_DodgeDrain(player, prevOwner, OJP_SaberBlockCost(player, bolt, trace->endpos));
    //[ExpSys]

    //[SaberLockSys]
    player->client->ps.saberLockFrame = 0; //break out of saberlocks.
    //[/SaberLockSys]

    //debounce time between blocks.
    player->client->ps.saberBlockTime = level.time + (600 - (player->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE]*200));

}