static void FireLasgun( gentity_t *self ) { // TODO: Merge this with other *Fire functions trace_t tr; vec3_t end; gentity_t *target; VectorMA( muzzle, 8192 * 16, forward, end ); G_UnlaggedOn( self, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, nullptr, nullptr, end, self->s.number, MASK_SHOT, 0 ); G_UnlaggedOff(); if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } target = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line G_SnapVectorTowards( tr.endpos, muzzle ); SendRangedHitEvent( self, target, &tr ); target->entity->Damage((float)LASGUN_DAMAGE, self, Vec3::Load(tr.endpos), Vec3::Load(forward), 0, (meansOfDeath_t)MOD_LASGUN); }
/* =============== areaZapFire =============== */ void areaZapFire( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *traceEnt; vec3_t mins, maxs; VectorSet( mins, -LEVEL2_AREAZAP_WIDTH, -LEVEL2_AREAZAP_WIDTH, -LEVEL2_AREAZAP_WIDTH ); VectorSet( maxs, LEVEL2_AREAZAP_WIDTH, LEVEL2_AREAZAP_WIDTH, LEVEL2_AREAZAP_WIDTH ); // set aiming directions AngleVectors( ent->client->ps.viewangles, forward, right, up ); CalcMuzzlePoint( ent, forward, right, up, muzzle ); VectorMA( muzzle, LEVEL2_AREAZAP_RANGE, forward, end ); G_UnlaggedOn( ent, muzzle, LEVEL2_AREAZAP_RANGE ); trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; if( ( ( traceEnt->client && traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) || ( traceEnt->s.eType == ET_BUILDABLE && BG_FindTeamForBuildable( traceEnt->s.modelindex ) == BIT_HUMANS ) ) && traceEnt->health > 0 ) { G_CreateNewZap( ent, traceEnt ); } }
static void FireLasgun( gentity_t *self ) { // TODO: Merge this with other *Fire functions trace_t tr; vec3_t end; gentity_t *target; VectorMA( muzzle, 8192 * 16, forward, end ); G_UnlaggedOn( self, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, self->s.number, MASK_SHOT ); G_UnlaggedOff(); if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } target = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line G_SnapVectorTowards( tr.endpos, muzzle ); SendRangedHitEvent( self, target, &tr ); if ( target->takedamage ) { G_Damage( target, self, self, forward, tr.endpos, LASGUN_DAMAGE, 0, MOD_LASGUN ); } }
/* ================ G_WideTrace Trace a bounding box against entities, but not the world Also check there is a line of sight between the start and end point ================ */ static void G_WideTrace( trace_t *tr, gentity_t *ent, float range, float width, float height, gentity_t **target ) { vec3_t mins, maxs; vec3_t end; VectorSet( mins, -width, -width, -height ); VectorSet( maxs, width, width, width ); *target = NULL; if( !ent->client ) return; G_UnlaggedOn( ent, muzzle, range + width ); VectorMA( muzzle, range, forward, end ); // Trace against entities trap_Trace( tr, muzzle, mins, maxs, end, ent->s.number, CONTENTS_BODY ); if( tr->entityNum != ENTITYNUM_NONE ) *target = &g_entities[ tr->entityNum ]; // Set range to the trace length plus the width, so that the end of the // LOS trace is close to the exterior of the target's bounding box range = Distance( muzzle, tr->endpos ) + width; VectorMA( muzzle, range, forward, end ); // Trace for line of sight against the world trap_Trace( tr, muzzle, NULL, NULL, end, ent->s.number, CONTENTS_SOLID ); if( tr->entityNum != ENTITYNUM_NONE ) *target = &g_entities[ tr->entityNum ]; G_UnlaggedOff( ); }
void bulletFire( gentity_t *ent, float spread, int damage, int mod ) { trace_t tr; vec3_t end; float r; float u; gentity_t *tent; gentity_t *traceEnt; r = random() * M_PI * 2.0f; u = sin( r ) * crandom() * spread * 16; r = cos( r ) * crandom() * spread * 16; VectorMA( muzzle, 8192 * 16, forward, end ); VectorMA( end, r, right, end ); VectorMA( end, u, up, end ); // don't use unlagged if this is not a client (e.g. turret) if ( ent->client ) { G_UnlaggedOn( ent, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff(); } else { trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); } if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } traceEnt = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); // send bullet impact if ( traceEnt->takedamage && ( traceEnt->s.eType == ET_PLAYER || traceEnt->s.eType == ET_BUILDABLE ) ) { tent = G_NewTempEntity( tr.endpos, EV_BULLET_HIT_FLESH ); tent->s.eventParm = traceEnt->s.number; } else { tent = G_NewTempEntity( tr.endpos, EV_BULLET_HIT_WALL ); tent->s.eventParm = DirToByte( tr.plane.normal ); } tent->s.otherEntityNum = ent->s.number; if ( traceEnt->takedamage ) { G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, mod ); } }
static void FireMassdriver( gentity_t *self ) { // TODO: Merge this with other *Fire functions trace_t tr; vec3_t end; gentity_t *target; VectorMA( muzzle, 8192.0f * 16.0f, forward, end ); G_UnlaggedOn( self, muzzle, 8192.0f * 16.0f ); trap_Trace( &tr, muzzle, nullptr, nullptr, end, self->s.number, MASK_SHOT, 0 ); G_UnlaggedOff(); if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } target = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line G_SnapVectorTowards( tr.endpos, muzzle ); SendRangedHitEvent( self, target, &tr ); if ( target->takedamage ) { G_Damage( target, self, self, forward, tr.endpos, MDRIVER_DMG, DAMAGE_KNOCKBACK, MOD_MDRIVER ); } }
void lightningGunFire( gentity_t *ent ) { vec3_t /*start, */end, mins, maxs, target_origin; trace_t tr; gentity_t *target; int damage; damage = LIGHTNING_DAMAGE; G_CombatStats_Fire( ent, CSW_LIGHTNING, damage ); VectorMA( muzzle, LIGHTNING_RANGE, forward, end ); G_UnlaggedOn( ent, muzzle, LIGHTNING_RANGE ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); if( tr.fraction == 1.0f || tr.entityNum == ENTITYNUM_NONE || ( tr.surfaceFlags & SURF_NOIMPACT ) ) { G_UnlaggedOff( ); return; } target = g_entities + tr.entityNum; if( target->s.eType == ET_PLAYER || target->s.eType == ET_BUILDABLE ) { float acc; VectorCopy( target->r.mins, mins ); VectorCopy( target->r.maxs, maxs ); VectorCopy( target->r.currentOrigin, target_origin ); BloodSpurt( ent, target, &tr ); acc = G_LightningAccuracy( muzzle, forward, mins, maxs, target_origin ); damage = MAX( round( (float)damage * acc ), 1 ); } else { gentity_t *tent; tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; } G_UnlaggedOff( ); G_Damage( target, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_LIGHTNING ); }
void shotgunFire( gentity_t *ent ) { gentity_t *tent; // send shotgun blast tent = G_NewTempEntity( muzzle, EV_SHOTGUN ); VectorScale( forward, 4096, tent->s.origin2 ); SnapVector( tent->s.origin2 ); tent->s.eventParm = rand() / ( RAND_MAX / 0x100 + 1 ); // seed for spread pattern tent->s.otherEntityNum = ent->s.number; G_UnlaggedOn( ent, muzzle, SHOTGUN_RANGE ); ShotgunPattern( tent->s.pos.trBase, tent->s.origin2, tent->s.eventParm, ent ); G_UnlaggedOff(); }
void shotgunFire( gentity_t *ent ) { gentity_t *tent; // send shotgun blast tent = G_TempEntity( muzzle, EV_SHOTGUN ); VectorScale( forward, 4096, tent->s.origin2 ); SnapVector( tent->s.origin2 ); tent->s.eventParm = rand() & 255; // seed for spread pattern tent->s.otherEntityNum = ent->s.number; G_UnlaggedOn( muzzle, 8192 * 16 ); ShotgunPattern( tent->s.pos.trBase, tent->s.origin2, tent->s.eventParm, ent ); G_UnlaggedOff(); }
/* =============== lasGunFire =============== *N/B: Kill means it was added. I ripped it from mgun. You can 'kill'/delete these if you want. */ void lasGunFire( gentity_t *ent, float spread ) //kill float spread { trace_t tr; vec3_t end; float r; //kill float u; //kill gentity_t *tent; gentity_t *traceEnt; r = random( ) * M_PI * 2.0f; //kill to u = sin( r ) * crandom( ) * spread * 16; r = cos( r ) * crandom( ) * spread * 16; VectorMA( muzzle, 8192 * 16, forward, end ); VectorMA( end, r, right, end ); VectorMA( end, u, up, end ); //kill // VectorMA( muzzle, 8192 * 16, forward, end ); //anyways included above G_UnlaggedOn( ent, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); // send impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } else { tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( traceEnt->takedamage ) G_Damage( traceEnt, ent, ent, forward, tr.endpos, LASGUN_DAMAGE, 0, MOD_LASGUN ); }
void painSawFire( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; // set aiming directions AngleVectors( ent->client->ps.viewangles, forward, right, up ); CalcMuzzlePoint( ent, forward, right, up, muzzle ); VectorMA( muzzle, PAINSAW_RANGE, forward, end ); G_UnlaggedOn( ent, muzzle, PAINSAW_RANGE ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; // send blood impact if( traceEnt->takedamage ) { vec3_t temp; //hack to get the particle system to line up with the weapon VectorCopy( tr.endpos, temp ); temp[ 2 ] -= 10.0f; if( traceEnt->client ) { tent = G_TempEntity( temp, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; } else tent = G_TempEntity( temp, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( traceEnt->takedamage ) G_Damage( traceEnt, ent, ent, forward, tr.endpos, PAINSAW_DAMAGE, DAMAGE_NO_KNOCKBACK, MOD_PAINSAW ); }
static void FireShotgun( gentity_t *self ) { gentity_t *tent; // instead of an EV_WEAPON_HIT_* event, send this so client can generate the same spread pattern tent = G_NewTempEntity( muzzle, EV_SHOTGUN ); VectorScale( forward, 4096, tent->s.origin2 ); SnapVector( tent->s.origin2 ); tent->s.eventParm = rand() / ( RAND_MAX / 0x100 + 1 ); // seed for spread pattern tent->s.otherEntityNum = self->s.number; // caclulate the pattern and do the damage G_UnlaggedOn( self, muzzle, SHOTGUN_RANGE ); ShotgunPattern( tent->s.pos.trBase, tent->s.origin2, tent->s.eventParm, self ); G_UnlaggedOff(); }
void massDriverFire( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; VectorMA( muzzle, 8192 * 16, forward, end ); G_UnlaggedOn( muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); // send impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } else { tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( traceEnt->takedamage ) { G_Damage( traceEnt, ent, ent, forward, tr.endpos, MDRIVER_DMG, 0, MOD_MDRIVER ); } }
/* ================ Trace a bounding box against entities, but not the world Also check there is a line of sight between the start and end point ================ */ static void G_WideTrace( trace_t *tr, gentity_t *ent, const float range, const float width, const float height, gentity_t **target ) { vec3_t mins, maxs, end; float halfDiagonal; *target = NULL; if ( !ent->client ) { return; } // Calculate box to use for trace VectorSet( maxs, width, width, height ); VectorNegate( maxs, mins ); halfDiagonal = VectorLength( maxs ); G_UnlaggedOn( ent, muzzle, range + halfDiagonal ); // Trace box against entities VectorMA( muzzle, range, forward, end ); trap_Trace( tr, muzzle, mins, maxs, end, ent->s.number, CONTENTS_BODY ); if ( tr->entityNum != ENTITYNUM_NONE ) { *target = &g_entities[ tr->entityNum ]; } // Line trace against the world, so we never hit through obstacles. // The range is reduced according to the former trace so we don't hit something behind the // current target. VectorMA( muzzle, Distance( muzzle, tr->endpos ) + halfDiagonal, forward, end ); trap_Trace( tr, muzzle, NULL, NULL, end, ent->s.number, CONTENTS_SOLID ); // In case we hit a different target, which can happen if two potential targets are close, // switch to it, so we will end up with the target we were looking at. if ( tr->entityNum != ENTITYNUM_NONE ) { *target = &g_entities[ tr->entityNum ]; } G_UnlaggedOff(); }
void massDriverFire( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; VectorMA( muzzle, 8192.0f * 16.0f, forward, end ); G_UnlaggedOn( ent, muzzle, 8192.0f * 16.0f ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff(); if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } traceEnt = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); // send impact if ( traceEnt->takedamage && ( traceEnt->s.eType == ET_BUILDABLE || traceEnt->s.eType == ET_PLAYER ) ) { BloodSpurt( ent, traceEnt, &tr ); } else { tent = G_NewTempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if ( traceEnt->takedamage ) { G_Damage( traceEnt, ent, ent, forward, tr.endpos, MDRIVER_DMG, 0, MOD_MDRIVER ); } }
/* =============== poisonCloud =============== */ void poisonCloud( gentity_t *ent ) { int entityList[ MAX_GENTITIES ]; vec3_t range = { LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE }; vec3_t mins, maxs; int i, num; gentity_t *humanPlayer; trace_t tr; VectorAdd( ent->client->ps.origin, range, maxs ); VectorSubtract( ent->client->ps.origin, range, mins ); G_UnlaggedOn( ent, ent->client->ps.origin, LEVEL1_PCLOUD_RANGE ); num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); for( i = 0; i < num; i++ ) { humanPlayer = &g_entities[ entityList[ i ] ]; if( humanPlayer->client && humanPlayer->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) { if( BG_InventoryContainsUpgrade( UP_LIGHTARMOUR, humanPlayer->client->ps.stats ) ) continue; if( BG_InventoryContainsUpgrade( UP_BATTLESUIT, humanPlayer->client->ps.stats ) ) continue; trap_Trace( &tr, muzzle, NULL, NULL, humanPlayer->s.origin, humanPlayer->s.number, MASK_SHOT ); //can't see target from here if( tr.entityNum == ENTITYNUM_WORLD ) continue; if( !( humanPlayer->client->ps.stats[ STAT_STATE ] & SS_POISONCLOUDED ) ) { humanPlayer->client->ps.stats[ STAT_STATE ] |= SS_POISONCLOUDED; humanPlayer->client->lastPoisonCloudedTime = level.time; humanPlayer->client->lastPoisonCloudedClient = ent; trap_SendServerCommand( humanPlayer->client->ps.clientNum, "poisoncloud" ); } } } G_UnlaggedOff( ); }
static void FireBullet( gentity_t *self, float spread, int damage, int mod ) { // TODO: Merge this with other *Fire functions trace_t tr; vec3_t end; float r, u; gentity_t *target; r = random() * M_PI * 2.0f; u = sin( r ) * crandom() * spread * 16; r = cos( r ) * crandom() * spread * 16; VectorMA( muzzle, 8192 * 16, forward, end ); VectorMA( end, r, right, end ); VectorMA( end, u, up, end ); // don't use unlagged if this is not a client (e.g. turret) if ( self->client ) { G_UnlaggedOn( self, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, self->s.number, MASK_SHOT ); G_UnlaggedOff(); } else { trap_Trace( &tr, muzzle, NULL, NULL, end, self->s.number, MASK_SHOT ); } if ( tr.surfaceFlags & SURF_NOIMPACT ) { return; } target = &g_entities[ tr.entityNum ]; SendRangedHitEvent( self, target, &tr ); if ( target->takedamage ) { G_Damage( target, self, self, forward, tr.endpos, damage, 0, mod ); } }
void lasGunFire( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; G_CombatStats_Fire( ent, CSW_LASGUN, LASGUN_DAMAGE ); VectorMA( muzzle, 8192 * 16, forward, end ); G_UnlaggedOn( ent, muzzle, 8192 * 16 ); trap_Trace( &tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; // snap the endpos to integers, but nudged towards the line SnapVectorTowards( tr.endpos, muzzle ); // send impact if( traceEnt->takedamage && (traceEnt->s.eType == ET_BUILDABLE || traceEnt->s.eType == ET_PLAYER ) ) { BloodSpurt( ent, traceEnt, &tr ); } else { tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( traceEnt->takedamage ) G_Damage( traceEnt, ent, ent, forward, tr.endpos, LASGUN_DAMAGE, 0, MOD_LASGUN ); }
/* =============== poisonCloud =============== */ void poisonCloud( gentity_t *ent ) { int entityList[ MAX_GENTITIES ]; vec3_t range = { LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE, LEVEL1_PCLOUD_RANGE }; vec3_t mins, maxs; int i, num; gentity_t *humanPlayer; trace_t tr; VectorAdd( ent->client->ps.origin, range, maxs ); VectorSubtract( ent->client->ps.origin, range, mins ); G_UnlaggedOn( ent, ent->client->ps.origin, LEVEL1_PCLOUD_RANGE ); num = trap_EntitiesInBox( mins, maxs, entityList, MAX_GENTITIES ); for ( i = 0; i < num; i++ ) { humanPlayer = &g_entities[ entityList[ i ] ]; if ( humanPlayer->client && humanPlayer->client->pers.teamSelection == TEAM_HUMANS ) { trap_Trace( &tr, muzzle, NULL, NULL, humanPlayer->s.origin, humanPlayer->s.number, CONTENTS_SOLID ); //can't see target from here if ( tr.entityNum == ENTITYNUM_WORLD ) { continue; } humanPlayer->client->ps.eFlags |= EF_POISONCLOUDED; humanPlayer->client->lastPoisonCloudedTime = level.time; trap_SendServerCommand( humanPlayer->client->ps.clientNum, "poisoncloud" ); } } G_UnlaggedOff(); }
/* =============== meleeAttack =============== */ void meleeAttack( gentity_t *ent, float range, float width, int damage, meansOfDeath_t mod ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; vec3_t mins, maxs; VectorSet( mins, -width, -width, -width ); VectorSet( maxs, width, width, width ); // set aiming directions AngleVectors( ent->client->ps.viewangles, forward, right, up ); CalcMuzzlePoint( ent, forward, right, up, muzzle ); VectorMA( muzzle, range, forward, end ); G_UnlaggedOn( ent, muzzle, range ); trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return; traceEnt = &g_entities[ tr.entityNum ]; // send blood impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( traceEnt->takedamage ) G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, mod ); }
/* =============== CheckPounceAttack =============== */ qboolean CheckPounceAttack( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; int damage; vec3_t mins, maxs; VectorSet( mins, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH, -LEVEL3_POUNCE_WIDTH ); VectorSet( maxs, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH, LEVEL3_POUNCE_WIDTH ); if( ent->client->ps.groundEntityNum != ENTITYNUM_NONE ) { ent->client->allowedToPounce = qfalse; ent->client->pmext.pouncePayload = 0; } if( !ent->client->allowedToPounce ) return qfalse; if( ent->client->ps.weaponTime ) return qfalse; // set aiming directions AngleVectors( ent->client->ps.viewangles, forward, right, up ); CalcMuzzlePoint( ent, forward, right, up, muzzle ); VectorMA( muzzle, LEVEL3_POUNCE_RANGE, forward, end ); G_UnlaggedOn( muzzle, LEVEL3_POUNCE_RANGE ); trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); //miss if( tr.fraction >= 1.0 ) return qfalse; if( tr.surfaceFlags & SURF_NOIMPACT ) return qfalse; traceEnt = &g_entities[ tr.entityNum ]; // send blood impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } if( !traceEnt->takedamage ) return qfalse; damage = (int)( ( (float)ent->client->pmext.pouncePayload / (float)LEVEL3_POUNCE_SPEED ) * LEVEL3_POUNCE_DMG ); ent->client->pmext.pouncePayload = 0; G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK|DAMAGE_NO_LOCDAMAGE, MOD_LEVEL3_POUNCE ); ent->client->allowedToPounce = qfalse; return qtrue; }
/* =============== CheckVenomAttack =============== */ qboolean CheckVenomAttack( gentity_t *ent ) { trace_t tr; vec3_t end; gentity_t *tent; gentity_t *traceEnt; vec3_t mins, maxs; int damage = LEVEL0_BITE_DMG; VectorSet( mins, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH, -LEVEL0_BITE_WIDTH ); VectorSet( maxs, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH, LEVEL0_BITE_WIDTH ); // set aiming directions AngleVectors( ent->client->ps.viewangles, forward, right, up ); CalcMuzzlePoint( ent, forward, right, up, muzzle ); VectorMA( muzzle, LEVEL0_BITE_RANGE, forward, end ); G_UnlaggedOn( ent, muzzle, LEVEL0_BITE_RANGE ); trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( tr.surfaceFlags & SURF_NOIMPACT ) return qfalse; traceEnt = &g_entities[ tr.entityNum ]; if( !traceEnt->takedamage ) return qfalse; if( !traceEnt->client && !traceEnt->s.eType == ET_BUILDABLE ) return qfalse; //allow bites to work against defensive buildables only if( traceEnt->s.eType == ET_BUILDABLE ) { if( traceEnt->s.modelindex != BA_H_MGTURRET && traceEnt->s.modelindex != BA_H_TESLAGEN ) return qfalse; //hackery damage *= 0.5f; } if( traceEnt->client ) { if( traceEnt->client->ps.stats[ STAT_PTEAM ] == PTE_ALIENS ) return qfalse; if( traceEnt->client->ps.stats[ STAT_HEALTH ] <= 0 ) return qfalse; } // send blood impact if( traceEnt->takedamage && traceEnt->client ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT ); tent->s.otherEntityNum = traceEnt->s.number; tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.weapon = ent->s.weapon; tent->s.generic1 = ent->s.generic1; //weaponMode } G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_LEVEL0_BITE ); return qtrue; }
/* =============== cancelBuildFire =============== */ void cancelBuildFire( gentity_t *ent ) { vec3_t forward, end; trace_t tr; gentity_t *traceEnt; vec3_t mins, maxs; int bHealth; // int damage = 20; // int hHealth; G_UnlaggedOn( ent, muzzle, LEVEL0_BITE_RANGE ); trap_Trace( &tr, muzzle, mins, maxs, end, ent->s.number, MASK_SHOT ); G_UnlaggedOff( ); if( ent->client->ps.stats[ STAT_BUILDABLE ] != BA_NONE ) { ent->client->ps.stats[ STAT_BUILDABLE ] = BA_NONE; return; } //repair buildable if( ent->client->ps.stats[ STAT_PTEAM ] == PTE_HUMANS ) { AngleVectors( ent->client->ps.viewangles, forward, NULL, NULL ); VectorMA( ent->client->ps.origin, 1000, forward, end ); trap_Trace( &tr, ent->client->ps.origin, NULL, NULL, end, ent->s.number, MASK_PLAYERSOLID ); traceEnt = &g_entities[ tr.entityNum ]; if( tr.fraction < 1.0 && ( traceEnt->s.eType == ET_BUILDABLE ) && ( traceEnt->biteam == ent->client->ps.stats[ STAT_PTEAM ] ) && ( ( ent->client->ps.weapon >= WP_HBUILD2 ) && ( ent->client->ps.weapon <= WP_HBUILD ) ) && traceEnt->spawned && traceEnt->health > 0 ) { if( ent->client->ps.stats[ STAT_MISC ] > 0 ) { G_AddEvent( ent, EV_BUILD_DELAY, ent->client->ps.clientNum ); return; } bHealth = BG_FindHealthForBuildable( traceEnt->s.modelindex ); traceEnt->health += HBUILD_HEALRATE; ent->client->pers.statscounters.repairspoisons++; level.humanStatsCounters.repairspoisons++; if( traceEnt->health > bHealth ) traceEnt->health = bHealth; if( traceEnt->health == bHealth ) G_AddEvent( ent, EV_BUILD_REPAIRED, 0 ); else G_AddEvent( ent, EV_BUILD_REPAIR, 0 ); } //never mind about this part onwards: doesn't work. //I just keep it here. else if ( tr.fraction < 1.0 && ( traceEnt->s.eType != ET_BUILDABLE ) && (traceEnt->biteam == ent->client->ps.stats[ STAT_PTEAM ] ) && ( ( ent->client->ps.weapon >= WP_HBUILD2 ) && ( ent->client->ps.weapon <= WP_HBUILD ) )) //same stats except not a buildable { if( ent->client->ps.stats[ STAT_MISC ] > 0 ) { G_AddEvent( ent, EV_BUILD_DELAY, ent->client->ps.clientNum ); return; } traceEnt->health += HBUILD_HEALRATE; ent->client->pers.statscounters.repairspoisons++; level.humanStatsCounters.repairspoisons++; /* hHealth = ( ent->health > client->ps.stats[ STAT_HEALTH ]); //client not declared etc.... just an example of what i want * for max health, but it isn't needed as vampire mode's 150%maxhealth is on. */ /* Play sounds for 'maxhealth reached' and stuff like that if( traceEnt->health == maxHealth ) G_AddEvent( ent, EV_BUILD_REPAIRED, 0 ); else G_AddEvent( ent, EV_BUILD_REPAIR, 0 ); */ } else if ((traceEnt->biteam != ent->client->ps.stats[ STAT_PTEAM ] ) && ( ( ent->client->ps.weapon >= WP_HBUILD2 ) && ( ent->client->ps.weapon <= WP_HBUILD ) )) //same stats except not on human team) { if( ent->client->ps.stats[ STAT_MISC ] > 0 ) { G_AddEvent( ent, EV_BUILD_DELAY, ent->client->ps.clientNum ); return; //Following is 'unreachable' according to the compiler // traceEnt->health -= 20; //do sum dmg! //damage //same for this part - but i just keep it in case server crashes due to a ckit killing. // G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_TRIGGER_HURT ); } } } else if( ent->client->ps.weapon == WP_ABUILD2 ) meleeAttack( ent, ABUILDER_CLAW_RANGE, ABUILDER_CLAW_WIDTH, ABUILDER_CLAW_DMG, MOD_ABUILDER_CLAW ); //melee attack for alien builder2 else if( ent->client->ps.weapon == WP_ABUILD ) meleeAttack( ent, ABUILDER_CLAW_RANGE, ABUILDER_CLAW_WIDTH, ABUILDER_CLAW_DMG, MOD_ABUILDER_CLAW ); //melee attack for alien builder }