//----------------------------------------------------------------- static void GM_CreateExplosion( gentity_t *self, const int boltID, qboolean doSmall = qfalse ) { if ( boltID >=0 ) { mdxaBone_t boltMatrix; vec3_t org, dir; gi.G2API_GetBoltMatrix( self->ghoul2, self->playerModel, boltID, &boltMatrix, self->currentAngles, self->currentOrigin, (cg.time?cg.time:level.time), NULL, self->s.modelScale ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, org ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, dir ); if ( doSmall ) { G_PlayEffect( "env/small_explode2", org, dir ); } else { G_PlayEffect( "env/med_explode2", org, dir ); } } }
void G_MissileReflectEffect( gentity_t *ent, vec3_t org, vec3_t dir ) #endif // _IMMERSION { //FIXME: have an EV_BOUNCE_MISSILE event that checks the s.weapon and does the appropriate effect switch( ent->s.weapon ) { case WP_BOWCASTER: #ifdef _IMMERSION G_PlayEffect( "bowcaster/deflect", hitEntNum, ent->currentOrigin, dir ); #else G_PlayEffect( "bowcaster/deflect", ent->currentOrigin, dir ); #endif // _IMMERSION break; case WP_BLASTER: case WP_BRYAR_PISTOL: case WP_BLASTER_PISTOL: default: #ifdef _IMMERSION G_PlayEffect( "blaster/deflect", hitEntNum, ent->currentOrigin, dir ); #else G_PlayEffect( "blaster/deflect", ent->currentOrigin, dir ); #endif // _IMMERSION break; } }
void RT_FlyStart( gentity_t *self ) {//switch to seeker AI for a while if ( TIMER_Done( self, "jetRecharge" ) && !RT_Flying( self ) ) { self->client->ps.gravity = 0; self->svFlags |= SVF_CUSTOM_GRAVITY; self->client->moveType = MT_FLYSWIM; //Inform NPC_HandleAIFlags we want to fly self->NPC->aiFlags |= NPCAI_FLY; self->lastInAirTime = level.time; //start jet effect self->client->jetPackTime = Q3_INFINITE; if ( self->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), self->playerModel, self->genericBolt1, self->s.number, self->currentOrigin, qtrue, qtrue ); } if ( self->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), self->playerModel, self->genericBolt2, self->s.number, self->currentOrigin, qtrue, qtrue ); } //take-off sound G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); if ( self->NPC ) { self->count = Q3_INFINITE; // SEEKER shot ammo count } } }
//--------------------------------------------------------- void thermalDetonatorExplode( gentity_t *ent ) //--------------------------------------------------------- { if ( !ent->count ) { G_Sound( ent, G_SoundIndex( "sound/weapons/thermal/warning.wav" ) ); ent->count = 1; ent->nextthink = level.time + 800; ent->svFlags |= SVF_BROADCAST;//so everyone hears/sees the explosion? } else { vec3_t pos; VectorSet( pos, ent->currentOrigin[0], ent->currentOrigin[1], ent->currentOrigin[2] + 8 ); ent->takedamage = qfalse; // don't allow double deaths! G_RadiusDamage( ent->currentOrigin, ent->owner, weaponData[WP_THERMAL].splashDamage, weaponData[WP_THERMAL].splashRadius, NULL, MOD_EXPLOSIVE_SPLASH ); G_PlayEffect( "thermal/explosion", ent->currentOrigin ); G_PlayEffect( "thermal/shockwave", ent->currentOrigin ); G_FreeEntity( ent ); } }
void Boba_FlyStart( gentity_t *self ) {//switch to seeker AI for a while if ( TIMER_Done( self, "jetRecharge" ) && !Boba_Flying( self ) ) { self->client->ps.gravity = 0; self->svFlags |= SVF_CUSTOM_GRAVITY; self->client->moveType = MT_FLYSWIM; //start jet effect self->client->jetPackTime = level.time + Q_irand( 3000, 10000 ); if ( self->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "boba/jetSP" ), self->playerModel, self->genericBolt1, self->s.number, self->currentOrigin, qtrue, qtrue ); } if ( self->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "boba/jetSP" ), self->playerModel, self->genericBolt2, self->s.number, self->currentOrigin, qtrue, qtrue ); } //take-off sound G_SoundOnEnt( self, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); //jet loop sound self->s.loopSound = G_SoundIndex( "sound/chars/boba/bf_jetpack_lp.wav" ); if ( self->NPC ) { self->count = Q3_INFINITE; // SEEKER shot ammo count } } }
//------------------------------------------------------------------------- void G_MissileBounceEffect( gentity_t *ent, vec3_t org, vec3_t dir, qboolean hitWorld ) { //FIXME: have an EV_BOUNCE_MISSILE event that checks the s.weapon and does the appropriate effect switch( ent->s.weapon ) { case WP_BOWCASTER: if ( hitWorld ) { G_PlayEffect( "bowcaster/bounce_wall", org, dir ); } else { G_PlayEffect( "bowcaster/deflect", ent->currentOrigin, dir ); } break; case WP_BLASTER: case WP_BRYAR_PISTOL: case WP_BLASTER_PISTOL: G_PlayEffect( "blaster/deflect", ent->currentOrigin, dir ); break; default: { gentity_t *tent = G_TempEntity( org, EV_GRENADE_BOUNCE ); VectorCopy( dir, tent->pos1 ); tent->s.weapon = ent->s.weapon; } break; } }
/* ------------------------- void Droid_Spin( void ) ------------------------- */ void Droid_Spin( void ) { vec3_t dir = {0,0,1}; R2D2_TurnAnims(); // Head is gone, spin and spark if ( NPC->client->NPC_class == CLASS_R5D2 ) { // No head? if (gi.G2API_GetSurfaceRenderStatus( &NPC->ghoul2[NPC->playerModel], "head" )) { if (TIMER_Done(NPC,"smoke") && !TIMER_Done(NPC,"droidsmoketotal")) { TIMER_Set( NPC, "smoke", 100); G_PlayEffect( "droid_smoke" , NPC->currentOrigin,dir); } if (TIMER_Done(NPC,"droidspark")) { TIMER_Set( NPC, "droidspark", Q_irand(100,500)); G_PlayEffect( "spark", NPC->currentOrigin,dir); } ucmd.forwardmove = Q_irand( -64, 64); if (TIMER_Done(NPC,"roam")) { TIMER_Set( NPC, "roam", Q_irand( 250, 1000 ) ); NPCInfo->desiredYaw = Q_irand( 0, 360 ); // Go in random directions } } else { if (TIMER_Done(NPC,"roam")) { NPCInfo->localState = LSTATE_NONE; } else { NPCInfo->desiredYaw = AngleNormalize360(NPCInfo->desiredYaw + 40); // Spin around } } } else { if (TIMER_Done(NPC,"roam")) { NPCInfo->localState = LSTATE_NONE; } else { NPCInfo->desiredYaw = AngleNormalize360(NPCInfo->desiredYaw + 40); // Spin around } } NPC_UpdateAngles( qtrue, qtrue ); }
void WP_FireScepter( gentity_t *ent, qboolean alt_fire ) {//just a straight beam int damage = 1; vec3_t start, end; trace_t tr; gentity_t *traceEnt = NULL, *tent; float shotRange = 8192; qboolean render_impact = qtrue; VectorCopy( muzzle, start ); WP_TraceSetStart( ent, start, vec3_origin, vec3_origin ); WP_MissileTargetHint(ent, start, forwardVec); VectorMA( start, shotRange, forwardVec, end ); gi.trace( &tr, start, NULL, NULL, end, ent->s.number, MASK_SHOT, G2_RETURNONHIT, 10 ); traceEnt = &g_entities[tr.entityNum]; if ( tr.surfaceFlags & SURF_NOIMPACT ) { render_impact = qfalse; } // always render a shot beam, doing this the old way because I don't much feel like overriding the effect. tent = G_TempEntity( tr.endpos, EV_DISRUPTOR_MAIN_SHOT ); tent->svFlags |= SVF_BROADCAST; VectorCopy( muzzle, tent->s.origin2 ); if ( render_impact ) { if ( tr.entityNum < ENTITYNUM_WORLD && traceEnt->takedamage ) { // Create a simple impact type mark that doesn't last long in the world G_PlayEffect( G_EffectIndex( "disruptor/flesh_impact" ), tr.endpos, tr.plane.normal ); int hitLoc = G_GetHitLocFromTrace( &tr, MOD_DISRUPTOR ); G_Damage( traceEnt, ent, ent, forwardVec, tr.endpos, damage, DAMAGE_EXTRA_KNOCKBACK, MOD_DISRUPTOR, hitLoc ); } else { G_PlayEffect( G_EffectIndex( "disruptor/wall_impact" ), tr.endpos, tr.plane.normal ); } } /* shotDist = shotRange * tr.fraction; for ( dist = 0; dist < shotDist; dist += 64 ) { //FIXME: on a really long shot, this could make a LOT of alerts in one frame... VectorMA( start, dist, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); } VectorMA( start, shotDist-4, forwardVec, spot ); AddSightEvent( ent, spot, 256, AEL_DISCOVERED, 50 ); */ }
//---------------------------------------------------------- void fx_explosion_trail_think( gentity_t *ent ) { vec3_t origin; trace_t tr; if ( ent->spawnflags & 1 ) // gravity { ent->s.pos.trType = TR_GRAVITY; } else { ent->s.pos.trType = TR_LINEAR; } EvaluateTrajectory( &ent->s.pos, level.time, origin ); gi.trace( &tr, ent->currentOrigin, vec3_origin, vec3_origin, origin, ent->owner ? ent->owner->s.number : ENTITYNUM_NONE, ent->clipmask, G2_RETURNONHIT, 10 ); if ( tr.fraction < 1.0f ) { // never explode or bounce on sky if ( !( tr.surfaceFlags & SURF_NOIMPACT )) { if ( ent->splashDamage && ent->splashRadius ) { G_RadiusDamage( tr.endpos, ent, ent->splashDamage, ent->splashRadius, ent, MOD_EXPLOSIVE_SPLASH ); } } if ( ent->fullName ) { // fxFile2....in other words, impact fx G_PlayEffect( ent->fullName, tr.endpos, tr.plane.normal ); } if ( VALIDSTRING( ent->soundSet ) == true ) { G_AddEvent( ent, EV_BMODEL_SOUND, CAS_GetBModelSound( ent->soundSet, BMS_END )); } G_FreeEntity( ent ); return; } G_RadiusDamage( origin, ent, ent->damage, ent->radius, ent, MOD_EXPLOSIVE_SPLASH ); // call the effect with the desired position and orientation G_PlayEffect( ent->fxID, origin, ent->currentAngles ); ent->nextthink = level.time + 50; gi.linkentity( ent ); }
void SandCreature_MoveEffect( void ) { vec3_t up = {0,0,1}; vec3_t org = {NPC->currentOrigin[0], NPC->currentOrigin[1], NPC->absmin[2]+2}; float playerDist = Distance( player->currentOrigin, NPC->currentOrigin ); if ( playerDist < 256 ) { CGCam_Shake( 0.75f*playerDist/256.0f, 250 ); } if ( level.time-NPC->client->ps.lastStationary > 2000 ) {//first time moving for at least 2 seconds //clear speakingtime TIMER_Set( NPC, "speaking", -level.time ); } if ( TIMER_Done( NPC, "breaching" ) && TIMER_Done( NPC, "breachDebounce" ) && TIMER_Done( NPC, "pain" ) && TIMER_Done( NPC, "attacking" ) && !Q_irand( 0, 10 ) ) {//Breach! //FIXME: only do this while moving forward? trace_t trace; //make him solid here so he can be hit/gets blocked on stuff. Check clear first. gi.trace( &trace, NPC->currentOrigin, NPC->mins, NPC->maxs, NPC->currentOrigin, NPC->s.number, MASK_NPCSOLID, (EG2_Collision)0, 0 ); if ( !trace.allsolid && !trace.startsolid ) { NPC->clipmask = MASK_NPCSOLID;//turn solid for a little bit NPC->contents = CONTENTS_BODY; //NPC->takedamage = qtrue;//can be shot? //FIXME: Breach sound? //FIXME: Breach effect? NPC_SetAnim( NPC, SETANIM_LEGS, BOTH_WALK2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD|SETANIM_FLAG_RESTART ); TIMER_Set( NPC, "breaching", NPC->client->ps.legsAnimTimer ); TIMER_Set( NPC, "breachDebounce", NPC->client->ps.legsAnimTimer+Q_irand( 0, 10000 ) ); } } if ( !TIMER_Done( NPC, "breaching" ) ) {//different effect when breaching //FIXME: make effect G_PlayEffect( G_EffectIndex( "env/sand_move_breach" ), org, up ); } else { G_PlayEffect( G_EffectIndex( "env/sand_move" ), org, up ); } NPC->s.loopSound = G_SoundIndex( "sound/chars/sand_creature/slither.wav" ); }
void RT_JetPackEffect( int duration ) { if ( NPC->genericBolt1 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), NPC->playerModel, NPC->genericBolt1, NPC->s.number, NPC->currentOrigin, duration, qtrue ); } if ( NPC->genericBolt2 != -1 ) { G_PlayEffect( G_EffectIndex( "rockettrooper/flameNEW" ), NPC->playerModel, NPC->genericBolt2, NPC->s.number, NPC->currentOrigin, duration, qtrue ); } //take-off sound G_SoundOnEnt( NPC, CHAN_ITEM, "sound/chars/boba/bf_blast-off.wav" ); }
void G_MissileReflectEffect( gentity_t *ent, vec3_t org, vec3_t dir ) { //FIXME: have an EV_BOUNCE_MISSILE event that checks the s.weapon and does the appropriate effect switch( ent->s.weapon ) { case WP_BOWCASTER: G_PlayEffect( "bowcaster/deflect", ent->currentOrigin, dir ); break; case WP_BLASTER: case WP_BRYAR_PISTOL: default: G_PlayEffect( "blaster/deflect", ent->currentOrigin, dir ); break; } }
/* ------------------------- Remote_Fire ------------------------- */ void Remote_Fire (void) { vec3_t delta1, enemy_org1, muzzle1; vec3_t angleToEnemy1; static vec3_t forward, vright, up; static vec3_t muzzle; gentity_t *missile; CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org1 ); VectorCopy( NPC->currentOrigin, muzzle1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forward, vright, up); missile = CreateMissile( NPC->currentOrigin, forward, 1000, 10000, NPC ); G_PlayEffect( "bryar/muzzle_flash", NPC->currentOrigin, forward ); missile->classname = "briar"; missile->s.weapon = WP_BRYAR_PISTOL; missile->damage = 10; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_ENERGY; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
//----------------------------------------------------- void turret_head_think( gentity_t *self ) //----------------------------------------------------- { gentity_t *top = &g_entities[self->r.ownerNum]; if ( !top ) { return; } if ( self->painDebounceTime > level.time ) { vec3_t v_up; VectorSet( v_up, 0, 0, 1 ); G_PlayEffect( EFFECT_SPARKS, self->r.currentOrigin, v_up ); if ( Q_irand( 0, 3) ) {//25% chance of still firing return; } } // if it's time to fire and we have an enemy, then gun 'em down! pushDebounce time controls next fire time if ( self->enemy && self->setTime < level.time && self->attackDebounceTime < level.time ) { vec3_t fwd, org; // set up our next fire time self->setTime = level.time + self->wait; VectorCopy( top->r.currentOrigin, org ); org[2] += top->r.maxs[2]-8; AngleVectors( top->r.currentAngles, fwd, NULL, NULL ); VectorMA( org, START_DIS, fwd, org ); turret_fire( top, org, fwd ); self->fly_sound_debounce_time = level.time;//used as lastShotTime } }
void NoghriGasCloudThink( gentity_t *self ) { self->nextthink = level.time + FRAMETIME; AddSightEvent( self->owner, self->currentOrigin, 200, AEL_DANGER, 50 ); if ( self->fx_time < level.time ) { vec3_t up = {0,0,1}; G_PlayEffect( "noghri_stick/gas_cloud", self->currentOrigin, up ); self->fx_time = level.time + 250; } if ( level.time - self->s.time <= 2500 ) { if ( !Q_irand( 0, 3-g_spskill->integer ) ) { G_RadiusDamage( self->currentOrigin, self->owner, Q_irand( 1, 4 ), self->splashRadius, self->owner, self->splashMethodOfDeath ); } } if ( level.time - self->s.time > 3000 ) { G_FreeEntity( self ); } }
void Boba_DoFlameThrower( gentity_t *self ) { if ( self->s.number < MAX_CLIENTS ) { if ( self->client ) { if ( !self->client->ps.forcePowerDuration[FP_LIGHTNING] ) { NPC_SetAnim( self, SETANIM_TORSO, BOTH_FORCELIGHTNING_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); self->client->ps.torsoAnimTimer = BOBA_FLAMEDURATION; G_SoundOnEnt( self, CHAN_WEAPON, "sound/weapons/boba/bf_flame.mp3" ); G_PlayEffect( G_EffectIndex("boba/fthrw"), self->playerModel, self->genericBolt3, self->s.number, self->s.origin, 1 ); self->client->ps.forcePowerDuration[FP_LIGHTNING] = 1; } Boba_FireFlameThrower( self ); } return; } if (!(NPCInfo->aiFlags&NPCAI_FLAMETHROW) && TIMER_Done(self, "nextAttackDelay")) { Boba_StartFlameThrower( self ); } if ( (NPCInfo->aiFlags&NPCAI_FLAMETHROW)) { Boba_FireFlameThrower( self ); } }
void DetPackBlow(gentity_t *self) { vec3_t v; self->pain = 0; self->die = 0; self->takedamage = qfalse; if ( self->target_ent ) {//we were attached to something, do *direct* damage to it! G_Damage( self->target_ent, self, &g_entities[self->r.ownerNum], v, self->r.currentOrigin, self->damage, 0, MOD_DET_PACK_SPLASH ); } G_RadiusDamage( self->r.currentOrigin, self->parent, self->splashDamage, self->splashRadius, self, self, MOD_DET_PACK_SPLASH ); v[0] = 0; v[1] = 0; v[2] = 1; if (self->count == -1) { VectorCopy(self->pos2, v); } G_PlayEffect(EFFECT_EXPLOSION_DETPACK, self->r.currentOrigin, v); self->think = G_FreeEntity; self->nextthink = level.time; }
/* ------------------------- Mark1Dead_FireBlaster - Shoot the left weapon, the multi-blaster ------------------------- */ void Mark1Dead_FireBlaster (void) { vec3_t muzzle1,muzzle_dir; gentity_t *missile; mdxaBone_t boltMatrix; int bolt; bolt = NPC->genericBolt1; gi.G2API_GetBoltMatrix( NPC->ghoul2, NPC->playerModel, bolt, &boltMatrix, NPC->currentAngles, NPC->currentOrigin, (cg.time?cg.time:level.time), NULL, NPC->s.modelScale ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, muzzle1 ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, muzzle_dir ); G_PlayEffect( "bryar/muzzle_flash", muzzle1, muzzle_dir ); missile = CreateMissile( muzzle1, muzzle_dir, 1600, 10000, NPC ); G_Sound( NPC, G_SoundIndex("sound/chars/mark1/misc/mark1_fire")); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; missile->damage = 1; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_ENERGY; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
void Boba_DustFallNear(const vec3_t origin, int dustcount) { if (!BobaActive) { return; } trace_t testTrace; vec3_t testDirection; vec3_t testStartPos; vec3_t testEndPos; VectorCopy(origin, testStartPos); for (int i=0; i<dustcount; i++) { testDirection[0] = (random() * 2.0f) - 1.0f; testDirection[1] = (random() * 2.0f) - 1.0f; testDirection[2] = 1.0f; VectorMA(origin, 1000.0f, testDirection, testEndPos); gi.trace (&testTrace, origin, NULL, NULL, testEndPos, (player && player->inuse)?(0):(ENTITYNUM_NONE), MASK_SHOT, (EG2_Collision)0, 0 ); if (!testTrace.startsolid && !testTrace.allsolid && testTrace.fraction>0.1f && testTrace.fraction<0.9f) { G_PlayEffect( "chunks/dustFall", testTrace.endpos, testTrace.plane.normal ); } } }
//------------------------------------------------------------------------------------------------------------ void auto_turret_die ( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int meansOfDeath ) //------------------------------------------------------------------------------------------------------------ { vec3_t forward = { 0,0, 1 }, pos; // Turn off the thinking of the base & use it's targets g_entities[self->r.ownerNum].think = NULL; g_entities[self->r.ownerNum].use = NULL; // clear my data self->die = NULL; self->takedamage = qfalse; self->s.health = self->health = 0; self->s.maxhealth = self->maxHealth = 0; self->s.loopSound = 0; self->s.shouldtarget = qfalse; //self->s.owner = MAX_CLIENTS; //not owned by any client VectorCopy( self->r.currentOrigin, pos ); pos[2] += self->r.maxs[2]*0.5f; G_PlayEffect( EFFECT_EXPLOSION_TURRET, pos, forward ); G_PlayEffectID( G_EffectIndex( "turret/explode" ), pos, forward ); if ( self->splashDamage > 0 && self->splashRadius > 0 ) { G_RadiusDamage( self->r.currentOrigin, attacker, self->splashDamage, self->splashRadius, attacker, NULL, MOD_UNKNOWN ); } self->s.weapon = 0; // crosshair code uses this to mark crosshair red if ( self->s.modelindex2 ) { // switch to damage model if we should self->s.modelindex = self->s.modelindex2; if (self->target_ent && self->target_ent->s.modelindex2) { self->target_ent->s.modelindex = self->target_ent->s.modelindex2; } VectorCopy( self->r.currentAngles, self->s.apos.trBase ); VectorClear( self->s.apos.trDelta ); if ( self->target ) { G_UseTargets( self, attacker ); } } else { ObjectDie( self, inflictor, attacker, damage, meansOfDeath ); } }
void G_ATSTCheckPain( gentity_t *self, gentity_t *other, const vec3_t point, int damage, int mod,int hitLoc ) { int newBolt; if ( rand() & 1 ) { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged1" ); } else { G_SoundOnEnt( self, CHAN_LESS_ATTEN, "sound/chars/atst/atst_damaged2" ); } if ((hitLoc==HL_ARM_LT) && (self->locationDamage[HL_ARM_LT] > LEFT_ARM_HEALTH)) { if (self->locationDamage[hitLoc] >= LEFT_ARM_HEALTH) // Blow it up? { newBolt = gi.G2API_AddBolt( &self->ghoul2[self->playerModel], "*flash3" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt1, self->s.number); ATST_PlayEffect( self, self->genericBolt1, "env/med_explode2" ); G_PlayEffect( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, newBolt, self->s.number, point); } gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "head_light_blaster_cann", TURN_OFF ); } } else if ((hitLoc==HL_ARM_RT) && (self->locationDamage[HL_ARM_RT] > RIGHT_ARM_HEALTH)) // Blow it up? { if (self->locationDamage[hitLoc] >= RIGHT_ARM_HEALTH) { newBolt = gi.G2API_AddBolt( &self->ghoul2[self->playerModel], "*flash4" ); if ( newBolt != -1 ) { // G_PlayEffect( "small_chunks", self->playerModel, self->genericBolt2, self->s.number); ATST_PlayEffect( self, self->genericBolt2, "env/med_explode2" ); G_PlayEffect( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, newBolt, self->s.number, point); } gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "head_concussion_charger", TURN_OFF ); } } }
//---------------------------------------------- void WP_flechette_alt_blow( gentity_t *ent ) //---------------------------------------------- { EvaluateTrajectory( &ent->s.pos, level.time, ent->currentOrigin ); // Not sure if this is even necessary, but correct origins are cool? G_RadiusDamage( ent->currentOrigin, ent->owner, ent->splashDamage, ent->splashRadius, NULL, MOD_EXPLOSIVE_SPLASH ); G_PlayEffect( "flechette/alt_blow", ent->currentOrigin ); G_FreeEntity( ent ); }
/* ------------------------- NPC_Mark1_Part_Explode ------------------------- */ void NPC_Mark1_Part_Explode( gentity_t *self, int bolt ) { if ( bolt >=0 ) { mdxaBone_t boltMatrix; vec3_t org, dir; gi.G2API_GetBoltMatrix( self->ghoul2, self->playerModel, bolt, &boltMatrix, self->currentAngles, self->currentOrigin, (cg.time?cg.time:level.time), NULL, self->s.modelScale ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, org ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, NEGATIVE_Y, dir ); G_PlayEffect( "env/med_explode2", org, dir ); G_PlayEffect( G_EffectIndex("blaster/smoke_bolton"), self->playerModel, bolt, self->s.number, org ); } }
void TouchTieBomb( gentity_t *self, gentity_t *other, trace_t *trace ) { // Stop the effect. G_StopEffect( G_EffectIndex( "ships/tiebomber_bomb_falling" ), self->playerModel, gi.G2API_AddBolt( &self->ghoul2[0], "model_root" ), self->s.number ); self->e_ThinkFunc = thinkF_G_FreeEntity; self->nextthink = level.time + FRAMETIME; G_PlayEffect( G_EffectIndex( "ships/tiebomber_explosion2" ), self->currentOrigin, self->currentAngles ); G_RadiusDamage( self->currentOrigin, self, 900, 500, self, MOD_EXPLOSIVE_SPLASH ); }
/* ------------------------- ImperialProbe_FireBlaster ------------------------- */ void ImperialProbe_FireBlaster(void) { vec3_t muzzle1,enemy_org1,delta1,angleToEnemy1; static vec3_t forward, vright, up; static vec3_t muzzle; gentity_t *missile; mdxaBone_t boltMatrix; //FIXME: use {0, NPC->client->ps.legsYaw, 0} gi.G2API_GetBoltMatrix( NPC->ghoul2, NPC->playerModel, NPC->genericBolt1, &boltMatrix, NPC->currentAngles, NPC->currentOrigin, (cg.time?cg.time:level.time), NULL, NPC->s.modelScale ); gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, muzzle1 ); G_PlayEffect( "bryar/muzzle_flash", muzzle1 ); G_Sound( NPC, G_SoundIndex( "sound/chars/probe/misc/fire" )); if (NPC->health) { CalcEntitySpot( NPC->enemy, SPOT_CHEST, enemy_org1 ); enemy_org1[0]+= Q_irand(0,10); enemy_org1[1]+= Q_irand(0,10); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forward, vright, up); } else { AngleVectors (NPC->currentAngles, forward, vright, up); } missile = CreateMissile( muzzle1, forward, 1600, 10000, NPC ); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; if ( g_spskill->integer <= 1 ) { missile->damage = 5; } else { missile->damage = 10; } missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_ENERGY; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
void TieBomberThink( gentity_t *self ) { // NOTE: Lerp2Angles will think this thinkfunc if the model is a misc_model_breakable. Watchout // for that in a script (try to just use ROFF's?). // Stop thinking, you're dead. if ( self->health <= 0 ) { return; } // Needed every think... self->nextthink = level.time + FRAMETIME; gentity_t *player = &g_entities[0]; vec3_t playerDir; float playerDist; //use player eyepoint VectorSubtract( player->currentOrigin, self->currentOrigin, playerDir ); playerDist = VectorNormalize( playerDir ); // Time to attack? if ( player->health > 0 && playerDist < MIN_PLAYER_DIST && self->attackDebounceTime < level.time ) { // Doesn't matter what model gets loaded here, as long as it exists. // It's only used as a point on to which the falling effect for the bomb // can be attached to (kinda inefficient, I know). char name1[200] = "models/players/gonk/model.glm"; gentity_t *bomb = G_CreateObject( self, self->s.pos.trBase, self->s.apos.trBase, 0, 0, TR_GRAVITY, 0 ); bomb->s.modelindex = G_ModelIndex( name1 ); gi.G2API_InitGhoul2Model( bomb->ghoul2, name1, bomb->s.modelindex, NULL_HANDLE, NULL_HANDLE, 0, 0); bomb->s.radius = 50; bomb->s.eFlags |= EF_NODRAW; // Make the bombs go forward in the bombers direction a little. vec3_t fwd, rt; AngleVectors( self->currentAngles, fwd, rt, NULL ); rt[2] -= 0.5f; VectorMA( bomb->s.pos.trBase, -30.0, rt, bomb->s.pos.trBase ); VectorScale( fwd, 300, bomb->s.pos.trDelta ); SnapVector( bomb->s.pos.trDelta ); // save net bandwidth // Start the effect. G_PlayEffect( G_EffectIndex( "ships/tiebomber_bomb_falling" ), bomb->playerModel, gi.G2API_AddBolt( &bomb->ghoul2[0], "model_root" ), bomb->s.number, bomb->currentOrigin, 1000, qtrue ); // Set the tie bomb to have a touch function, so when it hits the ground (or whatever), there's a nice 'boom'. bomb->e_TouchFunc = touchF_TouchTieBomb; self->attackDebounceTime = level.time + 1000; } }
void WP_Melee( gentity_t *ent ) //--------------------------------------------------------- { gentity_t *tr_ent; trace_t tr; vec3_t mins, maxs, end; int damage = ent->s.number ? (g_spskill->integer*2)+1 : 3; float range = ent->s.number ? 64 : 32; VectorMA( muzzle, range, forwardVec, end ); VectorSet( maxs, 6, 6, 6 ); VectorScale( maxs, -1, mins ); gi.trace ( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT, (EG2_Collision)0, 0 ); if ( tr.entityNum >= ENTITYNUM_WORLD ) { return; } tr_ent = &g_entities[tr.entityNum]; if ( ent->client && !PM_DroidMelee( ent->client->NPC_class ) ) { if ( ent->s.number || ent->alt_fire ) { damage *= Q_irand( 2, 3 ); } else { damage *= Q_irand( 1, 2 ); } } if ( tr_ent && tr_ent->takedamage ) { int dflags = DAMAGE_NO_KNOCKBACK; G_PlayEffect( G_EffectIndex( "melee/punch_impact" ), tr.endpos, forwardVec ); //G_Sound( tr_ent, G_SoundIndex( va("sound/weapons/melee/punch%d", Q_irand(1, 4)) ) ); if ( ent->NPC && (ent->NPC->aiFlags&NPCAI_HEAVY_MELEE) ) { //4x damage for heavy melee class damage *= 4; dflags &= ~DAMAGE_NO_KNOCKBACK; dflags |= DAMAGE_DISMEMBER; } G_Damage( tr_ent, ent, ent, forwardVec, tr.endpos, damage, dflags, MOD_MELEE ); } }
//--------------------------------------------------------- void WP_FireDisruptor( gentity_t *ent, qboolean alt_fire ) //--------------------------------------------------------- { if ( alt_fire ) { WP_DisruptorAltFire( ent ); } else { WP_DisruptorMainFire( ent ); } G_PlayEffect( G_EffectIndex( "disruptor/line_cap" ), wpMuzzle, wpFwd ); }
void NPC_GM_StartLaser( void ) { if ( !NPC->lockCount ) {//haven't already started a laser attack //warm up for the beam attack NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_RAISEWEAP2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); TIMER_Set( NPC, "beamDelay", NPC->client->ps.torsoAnimTimer ); TIMER_Set( NPC, "attackDelay", NPC->client->ps.torsoAnimTimer+3000 ); NPC->lockCount = 1; //turn on warmup effect G_PlayEffect( "galak/beam_warmup", NPC->s.number ); G_SoundOnEnt( NPC, CHAN_AUTO, "sound/weapons/galak/lasercharge.wav" ); } }
void G_MissileBounceEffect( gentity_t *ent, vec3_t org, vec3_t dir ) #endif // _IMMERSION { //FIXME: have an EV_BOUNCE_MISSILE event that checks the s.weapon and does the appropriate effect switch( ent->s.weapon ) { case WP_BOWCASTER: #ifdef _IMMERSION G_PlayEffect( "bowcaster/deflect", hitEntNum, ent->currentOrigin, dir ); #else G_PlayEffect( "bowcaster/deflect", ent->currentOrigin, dir ); #endif // _IMMERSION break; case WP_BLASTER: case WP_BRYAR_PISTOL: #ifdef _IMMERSION G_PlayEffect( "blaster/deflect", hitEntNum, ent->currentOrigin, dir ); #else G_PlayEffect( "blaster/deflect", ent->currentOrigin, dir ); #endif // _IMMERSION break; default: { gentity_t *tent = G_TempEntity( org, EV_GRENADE_BOUNCE ); VectorCopy( dir, tent->pos1 ); tent->s.weapon = ent->s.weapon; #ifdef _IMMERSION if ( hitEntNum != -1 ) { tent->s.saberActive = 1; tent->s.otherEntityNum = hitEntNum; } #endif // _IMMERSION } break; } }