/* * W_Touch_Plasma */ static void W_Touch_Plasma( edict_t *ent, edict_t *other, cplane_t *plane, int surfFlags ) { int hitType; vec3_t dir; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( ent ); return; } hitType = G_Projectile_HitStyle( ent, other ); if( hitType == PROJECTILE_TOUCH_NOT ) return; if( other->takedamage ) { VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTSPLASH ) // use hybrid direction from splash and projectile { G_SplashFrac4D( ENTNUM( other ), ent->s.origin, ent->projectileInfo.radius, dir, NULL, NULL, ent->timeDelta ); } else { VectorNormalize2( ent->velocity, dir ); } G_Damage( other, ent, ent->r.owner, dir, ent->velocity, ent->s.origin, ent->projectileInfo.maxDamage, ent->projectileInfo.maxKnockback, ent->projectileInfo.stun, DAMAGE_KNOCKBACK_SOFT, ent->style ); } W_Plasma_Explosion( ent, other, plane, surfFlags ); }
/* * W_Touch_Rocket */ static void W_Touch_Rocket( edict_t *ent, edict_t *other, cplane_t *plane, int surfFlags ) { int mod_splash; vec3_t dir; int hitType; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( ent ); return; } hitType = G_Projectile_HitStyle( ent, other ); if( hitType == PROJECTILE_TOUCH_NOT ) { return; } if( other->takedamage ) { int directHitDamage = ent->projectileInfo.maxDamage; VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTSPLASH ) { // use hybrid direction from splash and projectile G_SplashFrac4D( ENTNUM( other ), ent->s.origin, ent->projectileInfo.radius, dir, NULL, NULL, ent->timeDelta ); } else { VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTAIRHIT ) { directHitDamage += DIRECTAIRTHIT_DAMAGE_BONUS; } else if( hitType == PROJECTILE_TOUCH_DIRECTHIT ) { directHitDamage += DIRECTHIT_DAMAGE_BONUS; } } G_Damage( other, ent, ent->r.owner, dir, ent->velocity, ent->s.origin, directHitDamage, ent->projectileInfo.maxKnockback, ent->projectileInfo.stun, 0, ent->style ); } if( ent->s.effects & EF_STRONG_WEAPON ) { mod_splash = MOD_ROCKET_SPLASH_S; } else { mod_splash = MOD_ROCKET_SPLASH_W; } G_RadiusDamage( ent, ent->r.owner, plane, other, mod_splash ); // spawn the explosion if( !( surfFlags & SURF_NOIMPACT ) ) { edict_t *event; vec3_t explosion_origin; VectorMA( ent->s.origin, -0.02, ent->velocity, explosion_origin ); event = G_SpawnEvent( EV_ROCKET_EXPLOSION, DirToByte( plane ? plane->normal : NULL ), explosion_origin ); event->s.firemode = ( ent->s.effects & EF_STRONG_WEAPON ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK; event->s.weapon = ( ( ent->projectileInfo.radius * 1 / 8 ) > 255 ) ? 255 : ( ent->projectileInfo.radius * 1 / 8 ); } // free the rocket at next frame G_FreeEdict( ent ); }
/* * W_Touch_Grenade */ static void W_Touch_Grenade( edict_t *ent, edict_t *other, cplane_t *plane, int surfFlags ) { int hitType; vec3_t dir; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( ent ); return; } hitType = G_Projectile_HitStyle( ent, other ); if( hitType == PROJECTILE_TOUCH_NOT ) return; // don't explode on doors and plats that take damage if( !other->takedamage || ISBRUSHMODEL( other->s.modelindex ) ) { G_AddEvent( ent, EV_GRENADE_BOUNCE, ( ent->s.effects & EF_STRONG_WEAPON ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK, true ); return; } if( other->takedamage ) { int directHitDamage = ent->projectileInfo.maxDamage; VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTSPLASH ) // use hybrid direction from splash and projectile { G_SplashFrac4D( ENTNUM( other ), ent->s.origin, ent->projectileInfo.radius, dir, NULL, NULL, ent->timeDelta ); } else { VectorNormalize2( ent->velocity, dir ); // no direct hit bonuses for grenades /* if( hitType == PROJECTILE_TOUCH_DIRECTAIRHIT ) directHitDamage += DIRECTAIRTHIT_DAMAGE_BONUS; else if( hitType == PROJECTILE_TOUCH_DIRECTHIT ) directHitDamage += DIRECTHIT_DAMAGE_BONUS; */ } G_Damage( other, ent, ent->r.owner, dir, ent->velocity, ent->s.origin, directHitDamage, ent->projectileInfo.maxKnockback, ent->projectileInfo.stun, 0, ent->style ); } ent->enemy = other; W_Grenade_ExplodeDir( ent, plane ? plane->normal : NULL ); }
/* * W_Touch_GunbladeBlast */ static void W_Touch_GunbladeBlast( edict_t *ent, edict_t *other, cplane_t *plane, int surfFlags ) { vec3_t dir; int hitType; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( ent ); return; } hitType = G_Projectile_HitStyle( ent, other ); if( hitType == PROJECTILE_TOUCH_NOT ) return; if( other->takedamage ) { VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTSPLASH ) // use hybrid direction from splash and projectile { G_SplashFrac4D( ENTNUM( other ), ent->s.origin, ent->projectileInfo.radius, dir, NULL, NULL, ent->timeDelta ); } else { VectorNormalize2( ent->velocity, dir ); } G_Damage( other, ent, ent->r.owner, dir, ent->velocity, ent->s.origin, ent->projectileInfo.maxDamage, ent->projectileInfo.maxKnockback, ent->projectileInfo.stun, 0, ent->style ); } G_RadiusDamage( ent, ent->r.owner, plane, other, MOD_GUNBLADE_S ); // add explosion event if( ( !other->takedamage || ISBRUSHMODEL( other->s.modelindex ) ) ) { edict_t *event; event = G_SpawnEvent( EV_GUNBLADEBLAST_IMPACT, DirToByte( plane ? plane->normal : NULL ), ent->s.origin ); event->s.weapon = ( ( ent->projectileInfo.radius * 1/8 ) > 127 ) ? 127 : ( ent->projectileInfo.radius * 1/8 ); event->s.skinnum = ( ( ent->projectileInfo.maxKnockback * 1/8 ) > 255 ) ? 255 : ( ent->projectileInfo.maxKnockback * 1/8 ); } // free at next frame G_FreeEdict( ent ); }
/* * W_Touch_Bolt */ static void W_Touch_Bolt( edict_t *self, edict_t *other, cplane_t *plane, int surfFlags ) { edict_t *event; qboolean missed = qtrue; int hitType; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( self ); return; } if( other == self->enemy ) return; hitType = G_Projectile_HitStyle( self, other ); if( hitType == PROJECTILE_TOUCH_NOT ) return; if( other->takedamage ) { vec3_t invdir; G_Damage( other, self, self->r.owner, self->velocity, self->velocity, self->s.origin, self->projectileInfo.maxDamage, self->projectileInfo.maxKnockback, self->projectileInfo.stun, 0, MOD_ELECTROBOLT_W ); VectorNormalize2( self->velocity, invdir ); VectorScale( invdir, -1, invdir ); event = G_SpawnEvent( EV_BOLT_EXPLOSION, DirToByte( invdir ), self->s.origin ); event->s.firemode = FIRE_MODE_WEAK; if( other->r.client ) missed = qfalse; } else if( !( surfFlags & SURF_NOIMPACT ) ) { // add explosion event event = G_SpawnEvent( EV_BOLT_EXPLOSION, DirToByte( plane ? plane->normal : NULL ), self->s.origin ); event->s.firemode = FIRE_MODE_WEAK; } if( missed && self->r.client ) G_AwardPlayerMissedElectrobolt( self->r.owner, MOD_ELECTROBOLT_W ); // hit something that isnt a player G_FreeEdict( self ); }
/* * W_Touch_Projectile - Generic projectile touch func. Only for replacement in tests */ static void W_Touch_Projectile( edict_t *ent, edict_t *other, cplane_t *plane, int surfFlags ) { vec3_t dir, normal; int hitType; if( surfFlags & SURF_NOIMPACT ) { G_FreeEdict( ent ); return; } hitType = G_Projectile_HitStyle( ent, other ); if( hitType == PROJECTILE_TOUCH_NOT ) return; if( other->takedamage ) { VectorNormalize2( ent->velocity, dir ); if( hitType == PROJECTILE_TOUCH_DIRECTSPLASH ) // use hybrid direction from splash and projectile { G_SplashFrac4D( ENTNUM( other ), ent->s.origin, ent->projectileInfo.radius, dir, NULL, NULL, ent->timeDelta ); } else { VectorNormalize2( ent->velocity, dir ); } G_Damage( other, ent, ent->r.owner, dir, ent->velocity, ent->s.origin, ent->projectileInfo.maxDamage, ent->projectileInfo.maxKnockback, ent->projectileInfo.stun, 0, ent->style ); } G_RadiusDamage( ent, ent->r.owner, plane, other, MOD_EXPLOSIVE ); if( !plane->normal ) VectorSet( normal, 0, 0, 1 ); else VectorCopy( plane->normal, normal ); G_Gametype_ScoreEvent( NULL, "projectilehit", va( "%i %i %f %f %f", ent->s.number, surfFlags, normal[0], normal[1], normal[2] ) ); }