123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- // leave this line at the top of all AI_xxxx.cpp files for PCH reasons...
- #include "g_headers.h"
- //custom anims:
- //both_attack1 - running attack
- //both_attack2 - crouched attack
- //both_attack3 - standing attack
- //both_stand1idle1 - idle
- //both_crouch2stand1 - uncrouch
- //both_death4 - running death
- #define ASSASSIN_SHIELD_SIZE 75
- #define TURN_ON 0x00000000
- #define TURN_OFF 0x00000100
- ////////////////////////////////////////////////////////////////////////////////////////
- //
- ////////////////////////////////////////////////////////////////////////////////////////
- bool BubbleShield_IsOn()
- {
- return (NPC->flags&FL_SHIELDED);
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- //
- ////////////////////////////////////////////////////////////////////////////////////////
- void BubbleShield_TurnOn()
- {
- if (!BubbleShield_IsOn())
- {
- NPC->flags |= FL_SHIELDED;
- NPC->client->ps.powerups[PW_GALAK_SHIELD] = Q3_INFINITE;
- gi.G2API_SetSurfaceOnOff( &NPC->ghoul2[NPC->playerModel], "force_shield", TURN_ON );
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- //
- ////////////////////////////////////////////////////////////////////////////////////////
- void BubbleShield_TurnOff()
- {
- if ( BubbleShield_IsOn())
- {
- NPC->flags &= ~FL_SHIELDED;
- NPC->client->ps.powerups[PW_GALAK_SHIELD] = 0;
- gi.G2API_SetSurfaceOnOff( &NPC->ghoul2[NPC->playerModel], "force_shield", TURN_OFF );
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // Push A Particular Ent
- ////////////////////////////////////////////////////////////////////////////////////////
- void BubbleShield_PushEnt(gentity_t* pushed, vec3_t smackDir)
- {
- G_Damage(pushed, NPC, NPC, smackDir, NPC->currentOrigin, (g_spskill->integer+1)*Q_irand( 5, 10), DAMAGE_NO_KNOCKBACK, MOD_ELECTROCUTE);
- G_Throw(pushed, smackDir, 10);
- // Make Em Electric
- //------------------
- pushed->s.powerups |= (1 << PW_SHOCKED);
- if (pushed->client)
- {
- pushed->client->ps.powerups[PW_SHOCKED] = level.time + 1000;
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- // Go Through All The Ents Within The Radius Of The Shield And Push Them
- ////////////////////////////////////////////////////////////////////////////////////////
- void BubbleShield_PushRadiusEnts()
- {
- int numEnts;
- gentity_t* radiusEnts[128];
- const float radius = ASSASSIN_SHIELD_SIZE;
- vec3_t mins, maxs;
- vec3_t smackDir;
- float smackDist;
- for (int i = 0; i < 3; i++ )
- {
- mins[i] = NPC->currentOrigin[i] - radius;
- maxs[i] = NPC->currentOrigin[i] + radius;
- }
- numEnts = gi.EntitiesInBox(mins, maxs, radiusEnts, 128);
- for (int entIndex=0; entIndex<numEnts; entIndex++)
- {
- // Only Clients
- //--------------
- if (!radiusEnts[entIndex] || !radiusEnts[entIndex]->client)
- {
- continue;
- }
- // Don't Push Away Other Assassin Droids
- //---------------------------------------
- if (radiusEnts[entIndex]->client->NPC_class==NPC->client->NPC_class)
- {
- continue;
- }
- // Should Have Already Pushed The Enemy If He Touched Us
- //-------------------------------------------------------
- if (NPC->enemy && NPCInfo->touchedByPlayer==NPC->enemy && radiusEnts[entIndex]==NPC->enemy)
- {
- continue;
- }
- // Do The Vector Distance Test
- //-----------------------------
- VectorSubtract(radiusEnts[entIndex]->currentOrigin, NPC->currentOrigin, smackDir);
- smackDist = VectorNormalize(smackDir);
- if (smackDist<radius)
- {
- BubbleShield_PushEnt(radiusEnts[entIndex], smackDir);
- }
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////
- //
- ////////////////////////////////////////////////////////////////////////////////////////
- void BubbleShield_Update()
- {
- // Shields Go When You Die
- //-------------------------
- if (NPC->health<=0)
- {
- if (BubbleShield_IsOn())
- {
- BubbleShield_TurnOff();
- }
- return;
- }
- // Recharge Shields
- //------------------
- NPC->client->ps.stats[STAT_ARMOR] += 1;
- if (NPC->client->ps.stats[STAT_ARMOR]>250)
- {
- NPC->client->ps.stats[STAT_ARMOR] = 250;
- }
- // If We Have Enough Armor And Are Not Shooting Right Now, Kick The Shield On
- //----------------------------------------------------------------------------
- if (NPC->client->ps.stats[STAT_ARMOR]>100 && TIMER_Done(NPC, "ShieldsDown"))
- {
- // Check On Timers To Raise And Lower Shields
- //--------------------------------------------
- if ((level.time - NPCInfo->enemyLastSeenTime)<1000 && TIMER_Done(NPC, "ShieldsUp"))
- {
- TIMER_Set(NPC, "ShieldsDown", 2000); // Drop Shields
- TIMER_Set(NPC, "ShieldsUp", Q_irand(4000, 5000)); // Then Bring Them Back Up For At Least 3 sec
- }
- BubbleShield_TurnOn();
- if (BubbleShield_IsOn())
- {
- // Update Our Shader Value
- //-------------------------
- NPC->client->renderInfo.customRGBA[0] =
- NPC->client->renderInfo.customRGBA[1] =
- NPC->client->renderInfo.customRGBA[2] =
- NPC->client->renderInfo.customRGBA[3] = (NPC->client->ps.stats[STAT_ARMOR] - 100);
- // If Touched By An Enemy, ALWAYS Shove Them
- //-------------------------------------------
- if (NPC->enemy && NPCInfo->touchedByPlayer==NPC->enemy)
- {
- vec3_t dir;
- VectorSubtract(NPC->enemy->currentOrigin, NPC->currentOrigin, dir);
- VectorNormalize(dir);
- BubbleShield_PushEnt(NPC->enemy, dir);
- }
- // Push Anybody Else Near
- //------------------------
- BubbleShield_PushRadiusEnts();
- }
- }
- // Shields Gone
- //--------------
- else
- {
- BubbleShield_TurnOff();
- }
- }
|