//========================================================= // CheckRangeAttack2 - toss grenade is enemy gets in the way and is too close. //========================================================= BOOL CHAssassin :: CheckRangeAttack2 ( float flDot, float flDist ) { m_fThrowGrenade = FALSE; if ( !FBitSet ( m_hEnemy->pev->flags, FL_ONGROUND ) ) { // don't throw grenades at anything that isn't on the ground! return FALSE; } // don't get grenade happy unless the player starts to piss you off if ( m_iFrustration <= 2) return FALSE; if ( m_flNextGrenadeCheck < gpGlobals->time && !HasConditions( bits_COND_ENEMY_OCCLUDED ) && flDist <= 512 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */ ) { Vector vecToss = VecCheckThrow( pev, GetGunPosition( ), m_hEnemy->Center(), flDist, 0.5 ); // use dist as speed to get there in 1 second if ( vecToss != g_vecZero ) { m_vecTossVelocity = vecToss; // throw a hand grenade m_fThrowGrenade = TRUE; return TRUE; } } return FALSE; }
bool CEntity::FBoxVisible(CEntity *pEntity, Vector *pvHit, unsigned char *ucBodyPart) { if (ucBodyPart) *ucBodyPart = 0; // don't look through water if (IsInWater() != pEntity->IsInWater()) return false; bool fVisible = false; traceresult_t tr; // Check direct Line to waist Vector vecLookerOrigin = GetGunPosition(); Vector vecTarget = pEntity->GetOrigin(); tr = TestLine(vecLookerOrigin, vecTarget, true, NULL); if (tr.fraction >= 1.0) { if (pvHit) *pvHit = tr.endpos; if (ucBodyPart) *ucBodyPart |= WAIST_VISIBLE; fVisible = true; } // Check direct Line to head vecTarget = pEntity->GetGunPosition(); tr = TestLine(vecLookerOrigin, vecTarget, true, NULL); if (tr.fraction >= 1.0) { if (pvHit) *pvHit = tr.endpos; if (ucBodyPart) *ucBodyPart |= HEAD_VISIBLE; fVisible = true; } if (fVisible) return true; // Nothing visible - check randomly other parts of body for (int i = 0; i < 5; i++) { vecTarget.x = RandomFloat(pEntity->GetAbsMin().x, pEntity->GetAbsMax().x); vecTarget.y = RandomFloat(pEntity->GetAbsMin().y, pEntity->GetAbsMax().y); vecTarget.z = RandomFloat(pEntity->GetAbsMin().z, pEntity->GetAbsMax().z); tr = TestLine(vecLookerOrigin, vecTarget, true, NULL); if (tr.fraction == 1.0) { // Return seen position if (pvHit) *pvHit = tr.endpos; if (ucBodyPart) *ucBodyPart |= CUSTOM_VISIBLE; return true; } } return false; // it's invisible }
//========================================================= // FVisible - returns true if a line can be traced from // the caller's eyes to the target //========================================================= bool CEntity::FVisible(const Vector &vecDest) { // don't look through water if (IsLiquid(GetGunPosition()) != IsLiquid(vecDest)) return false; // check if line of sight to object is not blocked (i.e. visible) return (TestLine(EyePosition(), vecDest).fraction >= 1.0); }
//========================================================= // FInViewCone - returns true is the passed vector is in // the caller's forward view cone. //========================================================= bool CEntity::FInViewCone(Vector *pOrigin, float fov) { if (fov <= 0) fov = GetFov(); Vector forward; GetViewAngles().AngleVectors(&forward); Vector vecLOS = (*pOrigin - GetGunPosition()).Normalize(); float flDot = DotProduct(vecLOS, forward); return (flDot >= cos((fov / 2) * (M_PI / 180))); }
void Bot::FocusEnemy (void) { // aim for the head and/or body Vector enemyOrigin = GetAimPosition (); m_lookAt = enemyOrigin; if (m_enemySurpriseTime > engine->GetTime ()) return; enemyOrigin = (enemyOrigin - GetGunPosition ()).SkipZ (); float distance = enemyOrigin.GetLength (); // how far away is the enemy scum? if (distance < 128) { if (m_currentWeapon == WEAPON_KNIFE) { if (distance < 80.0f) m_wantsToFire = true; } else m_wantsToFire = true; } else { if (m_currentWeapon == WEAPON_KNIFE) m_wantsToFire = true; else { float dot = GetShootingConeDeviation (GetEntity (), &m_enemyOrigin); if (dot < 0.90) m_wantsToFire = false; else { float enemyDot = GetShootingConeDeviation (m_enemy, &pev->origin); // enemy faces bot? if (enemyDot >= 0.90) m_wantsToFire = true; else { if (dot > 0.99) m_wantsToFire = true; else m_wantsToFire = false; } } } } }
//========================================================= // Shoot //========================================================= void CHAssassin :: Shoot ( void ) { if (m_hEnemy == NULL) { return; } Vector vecShootOrigin = GetGunPosition(); Vector vecShootDir = ShootAtEnemy( vecShootOrigin ); if (m_flLastShot + 2 < gpGlobals->time) { m_flDiviation = 0.10; } else { m_flDiviation -= 0.01; if (m_flDiviation < 0.02) m_flDiviation = 0.02; } m_flLastShot = gpGlobals->time; UTIL_MakeVectors ( pev->angles ); Vector vecShellVelocity = gpGlobals->v_right * RANDOM_FLOAT(40,90) + gpGlobals->v_up * RANDOM_FLOAT(75,200) + gpGlobals->v_forward * RANDOM_FLOAT(-40, 40); EjectBrass ( pev->origin + gpGlobals->v_up * 32 + gpGlobals->v_forward * 12, vecShellVelocity, pev->angles.y, m_iShell, TE_BOUNCE_SHELL); FireBullets(1, vecShootOrigin, vecShootDir, Vector( m_flDiviation, m_flDiviation, m_flDiviation ), 2048, BULLET_MONSTER_9MM ); // shoot +-8 degrees switch(RANDOM_LONG(0,1)) { case 0: EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun1.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM); break; case 1: EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/pl_gun2.wav", RANDOM_FLOAT(0.6, 0.8), ATTN_NORM); break; } pev->effects |= EF_MUZZLEFLASH; Vector angDir = UTIL_VecToAngles( vecShootDir ); SetBlending( 0, angDir.x ); m_cAmmoLoaded--; }
//========================================================= // CheckRangeAttack1 - drop a cap in their ass // //========================================================= BOOL CHAssassin :: CheckRangeAttack1 ( float flDot, float flDist ) { if ( !HasConditions( bits_COND_ENEMY_OCCLUDED ) && flDist > 64 && flDist <= 2048 /* && flDot >= 0.5 */ /* && NoFriendlyFire() */ ) { TraceResult tr; Vector vecSrc = GetGunPosition(); // verify that a bullet fired from the gun will hit the enemy before the world. UTIL_TraceLine( vecSrc, m_hEnemy->BodyTarget(vecSrc), dont_ignore_monsters, ENT(pev), &tr); if ( tr.flFraction == 1 || tr.pHit == m_hEnemy->edict() ) { return TRUE; } } return FALSE; }
bool RadioCreate( edict_t *pEntity ) { // Create the radio and stick to the wall entvars_t *pPev = VARS( pEntity ); if (pPev->iuser1 > 0) return 0; // make sure we dont already have a radio int radiocount = 0; int i = 1; char *pClassname; edict_t *frontEnt; for (i; i < 1025; i++) { frontEnt = INDEXENT ( i ); if (frontEnt) { pClassname = (char *)STRING(frontEnt->v.classname); if (FStrEq("building_radio", pClassname)) { if (frontEnt->v.euser4 == pEntity) { radiocount++; } } } } if (AdminLoggedIn[ENTINDEX(pEntity)] == 0) { if (radiocount >= 2) { ClientPrint( pPev, HUD_PRINTTALK, "* Cant have more than 2 radios!\n"); return 0; } } UTIL_MakeVectors( pPev->v_angle + pPev->punchangle ); Vector vecSrc = GetGunPosition( pEntity ); Vector vecAiming = gpGlobals->v_forward; TraceResult tr; UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, pEntity , &tr ); if (tr.flFraction < 1.0 || AdminLoggedIn[ENTINDEX(pEntity)]) { if (tr.pHit && !(tr.pHit->v.flags & FL_CONVEYOR) && (FStrEq((char *)STRING(tr.pHit->v.classname), "worldspawn") || FStrEq((char *)STRING(tr.pHit->v.classname), "func_wall") || AdminLoggedIn[ENTINDEX(pEntity)] || FStrEq((char *)STRING(tr.pHit->v.classname), "building_dancemachine"))) // Make sure it isnt a conveyor! { Vector angles = UTIL_VecToAngles( tr.vecPlaneNormal ); if ((angles.x > 30 || angles.x < -30) && AdminLoggedIn[ENTINDEX(pEntity)] == 0) { ClientPrint( pPev, HUD_PRINTTALK, "* Can't place radios on floors or cielings!\n"); return 0; } // Create the camera here! Vector vecOri = tr.vecEndPos + tr.vecPlaneNormal * 14; //Vector vecOri = tr.vecEndPos + tr.vecPlaneNormal * 15; int maxdist = (int)CVAR_GET_FLOAT("sa_radiospread"); // make sure we arent placing it within 400 units of another radio for (i=1; i < 1025; i++) { frontEnt = INDEXENT ( i ); if (frontEnt) { pClassname = (char *)STRING(frontEnt->v.classname); if (FStrEq("building_radio", pClassname)) { if ((frontEnt->v.origin - vecOri).Length() < maxdist && AdminLoggedIn[ENTINDEX(pEntity)] == 0) { ClientPrint( pPev, HUD_PRINTTALK, "* Can't place a radio so close to another radio!\n"); return 0; } } } } KeyValueData kvd; //edict_t *pent = CREATE_ENTITY(); //edict_t *pent = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); edict_t *tEntity; tEntity = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); entvars_t *pRunOnPev; pRunOnPev = VARS(tEntity); char buf[80]; sprintf( buf, "%s", "building_radio"); // Set the KEYVALUES here! kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = buf; DispatchKeyValue( tEntity, &kvd ); // place this in front pRunOnPev->origin = vecOri; SET_ORIGIN( tEntity , vecOri ); pRunOnPev->angles = angles; //DispatchSpawn( ENT( pRunOnPev ) ); pRunOnPev->solid = SOLID_BBOX; SET_MODEL( ENT( pRunOnPev ) , "avatar-x/avadd16.avfil"); UTIL_SetSize( pRunOnPev, Vector( -2, -2 ,-2) - (tr.vecPlaneNormal * 15), Vector(2, 2, 16) - (tr.vecPlaneNormal * 15)); pRunOnPev->takedamage = DAMAGE_YES; pRunOnPev->max_health = 40 + 10000; pRunOnPev->health = 40 + 10000; pRunOnPev->euser4 = pEntity; /* edict_t *pent; pent = CREATE_NAMED_ENTITY(MAKE_STRING("xen_tree")); entvars_t *pv = VARS( pent ); pv->origin = vecOri; SET_ORIGIN(pent, vecOri); kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = "xen_tree"; DispatchKeyValue( pent, &kvd ); DispatchSpawn(pent); //pev->angles = angles; */ //pev->iuser1 = angles.y; //pv->vuser3 = angles; // for now don't take damage //pev->takedamage = DAMAGE_YES; //pev->max_health = 40 + 10000; //pev->health = 40 + 10000; /* // Call the SPAWN routine to set more stuff kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = "building_radio"; //DispatchKeyValue( pent, &kvd ); kvd.fHandled = FALSE; */ RadioSpawn( tEntity ); return 1; } else { ClientPrint( pPev, HUD_PRINTTALK, "* Couldn't place radio here!\n"); return 0; } } else { ClientPrint( pPev, HUD_PRINTTALK, "* Couldn't place radio here!\n"); } return 0; }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. //========================================================= void CZombie :: HandleAnimEvent( MonsterEvent_t *pEvent ) { switch( pEvent->event ) { case ZOMBIE_AE_ATTACK_RANGE: { Vector vecToss; UTIL_MakeAimVectors ( pev->angles ); vecToss = VecCheckThrow( pev, GetGunPosition(), m_vecEnemyLKP, 750, 1 ); AttackMissSound(); CGuts::ShootGuts(pev, GetGunPosition(), vecToss); } break; case ZOMBIE_AE_ATTACK_RIGHT: { // do stuff for this event. CBaseEntity *pHurt = CheckTraceHullAttack( 70, zombie_dmg_melee.value, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = -18; pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity - gpGlobals->v_right * 100; } AttackHitSound(); } else AttackMissSound(); if (RANDOM_LONG(0,1)) AttackSound(); } break; case ZOMBIE_AE_ATTACK_LEFT: { // do stuff for this event. CBaseEntity *pHurt = CheckTraceHullAttack( 70, zombie_dmg_melee.value, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.z = 18; pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_right * 100; } AttackHitSound(); } else AttackMissSound(); if (RANDOM_LONG(0,1)) AttackSound(); } break; case ZOMBIE_AE_ATTACK_BOTH: { // do stuff for this event. CBaseEntity *pHurt = CheckTraceHullAttack( 70, zombie_dmg_melee.value*2, DMG_SLASH ); if ( pHurt ) { if ( pHurt->pev->flags & (FL_MONSTER|FL_CLIENT) ) { pHurt->pev->punchangle.x = 5; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * -100; } AttackHitSound(); } else AttackMissSound(); if (RANDOM_LONG(0,1)) AttackSound(); } break; default: CBaseMonster::HandleAnimEvent( pEvent ); break; } }
bool DanceCreate( edict_t *pEntity ) { // Create the dance machine entvars_t *pPev = VARS( pEntity ); if (AdminLoggedIn[ENTINDEX(pEntity)] == 0) { ClientPrint( pPev, HUD_PRINTTALK, "* Admin only feature\n"); return 0; } UTIL_MakeVectors( pPev->v_angle + pPev->punchangle ); Vector vecSrc = GetGunPosition( pEntity ); Vector vecAiming = gpGlobals->v_forward; TraceResult tr; UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 128, dont_ignore_monsters, pEntity , &tr ); //if (tr.flFraction < 1.0) //{ Vector angles = UTIL_VecToAngles( tr.vecPlaneNormal ); // Create the paper here! KeyValueData kvd; edict_t *tEntity; tEntity = CREATE_NAMED_ENTITY(MAKE_STRING("info_target")); entvars_t *pRunOnPev; pRunOnPev = VARS(tEntity); // Set the KEYVALUES here! kvd.fHandled = FALSE; kvd.szClassName = NULL; kvd.szKeyName = "classname"; kvd.szValue = "building_dancemachine"; DispatchKeyValue( tEntity, &kvd ); // place this in front Vector vecOri = tr.vecEndPos; pRunOnPev->origin = vecOri; pRunOnPev->solid = SOLID_BBOX; SET_ORIGIN( tEntity , vecOri ); pRunOnPev->angles = angles; pRunOnPev->solid = SOLID_BBOX; SET_MODEL( ENT( pRunOnPev ) , "models/sphere.mdl"); UTIL_SetSize( pRunOnPev, Vector( -16, -16 , -16), Vector(16, 16, 16) ); pRunOnPev->takedamage = DAMAGE_NO; pRunOnPev->max_health = 40 + 10000; pRunOnPev->health = 40 + 10000; pRunOnPev->euser4 = pEntity; pRunOnPev->movetype = MOVETYPE_FLY; //DROP_TO_FLOOR( tEntity ); // play deploy sound EMIT_SOUND_DYN2( tEntity, CHAN_VOICE, "weapons/mine_deploy.wav", 1.0, ATTN_NORM , 0, 100); //unOnPev->iuser2 = pRunOnPev->euser4->v.team; // Set the team this radio belongs to pRunOnPev->nextthink = gpGlobals->time + 1; pRunOnPev->avelocity.y = 50; sprintf( EntData[ENTINDEX(tEntity)].digitgroup, "%s", Cmd_Argv(1)); if (FStrEq(Cmd_Argv(2), "rot")) { // rotates. get the distance, angular speed, and initial angle pRunOnPev->iuser1 = atoi(Cmd_Argv(3)); pRunOnPev->fuser1 = atof(Cmd_Argv(4)); pRunOnPev->iuser3 = atoi(Cmd_Argv(5)); // mark original origin pRunOnPev->vuser1 = pEntity->v.origin; pRunOnPev->avelocity.y = 0; } return 0; }
//========================================================= // HandleAnimEvent - catches the monster-specific messages // that occur when tagged animation frames are played. // // Returns number of events handled, 0 if none. //========================================================= void CFriend :: HandleAnimEvent( MonsterEvent_t *pEvent ) { Vector vecGunPos; Vector vecGunAngles; GetAttachment( 0, vecGunPos, vecGunAngles ); switch( pEvent->event ) { case HGRUNT_AE_BURST1: BarneyFirePistol(); break; //sys case HGRUNT_AE_BURST2: case HGRUNT_AE_BURST3: BarneyFirePistol(); break; /* case HGRUNT_AE_KICK: { CBaseEntity *pHurt = Kick(); if ( pHurt ) { // SOUND HERE! UTIL_MakeVectors( pev->angles ); pHurt->pev->punchangle.x = 15; pHurt->pev->velocity = pHurt->pev->velocity + gpGlobals->v_forward * 100 + gpGlobals->v_up * 50; pHurt->TakeDamage( pev, pev, gSkillData.hgruntDmgKick, DMG_CLUB ); } } break; */ case HGRUNT_AE_DROP_GUN: { //SP: si tiene el flag de "no tirar arma" cerrar con break y no ejecutar //mas codigo if (pev->spawnflags & SF_MONSTER_NO_WPN_DROP) break; //LRC Vector vecGunPos; Vector vecGunAngles; GetAttachment( 0, vecGunPos, vecGunAngles ); SetBodygroup( GUN_GROUP, GUN_NONE ); CBaseEntity *pItem; // now spawn a gun. //if (FBitSet( pev->weapons, HGRUNT_SHOTGUN )) if (pev->frags) { pItem = DropItem( "weapon_shotgun", vecGunPos, vecGunAngles ); pItem->pev->spawnflags |= SF_NORESPAWN; // No respawn } else { pItem = DropItem( "weapon_m16", vecGunPos, vecGunAngles ); pItem->pev->spawnflags |= SF_NORESPAWN; // No respawn } //if -> crash, remove the following // pItem->pev->avelocity = Vector ( RANDOM_FLOAT( -222, 222 ), RANDOM_FLOAT( -222, 222 ),RANDOM_FLOAT( -222, 222 ) ); } break; case HGRUNT_AE_RELOAD: EMIT_SOUND( ENT(pev), CHAN_WEAPON, "hgrunt/gr_reload1.wav", 1, ATTN_NORM ); m_cAmmoLoaded = m_cClipSize; ClearConditions(bits_COND_NO_AMMO_LOADED); // DropItem( "item_clip_rifle", vecGunPos, vecGunAngles );//test break; case FBARNEY_AE_DRAW: if (pev->frags)//shotgun SetBodygroup( GUN_GROUP, GUN_SHOTGUN ); else SetBodygroup( GUN_GROUP, GUN_MP5 ); m_fGunDrawn = TRUE; break; case HGRUNT_AE_GREN_DROP: { UTIL_MakeVectors( pev->angles ); CGrenade::ShootTimed( pev, pev->origin + gpGlobals->v_forward * 17 - gpGlobals->v_right * 27 + gpGlobals->v_up * 6, g_vecZero, 3 ); } break; case HGRUNT_AE_GREN_TOSS: { UTIL_MakeVectors( pev->angles ); // CGrenade::ShootTimed( pev, pev->origin + gpGlobals->v_forward * 34 + Vector (0, 0, 32), m_vecTossVelocity, 3.5 ); CGrenade::ShootTimed( pev, GetGunPosition(), m_vecTossVelocity, 3.5 ); m_fThrowGrenade = FALSE; m_flNextGrenadeCheck = gpGlobals->time + 6;// wait six seconds before even looking again to see if a grenade can be thrown. } break; default: CTalkMonster::HandleAnimEvent( pEvent ); } }
//========================================================= // CheckRangeAttack2 - this checks the Grunt's grenade // attack. //========================================================= BOOL CFriend :: CheckRangeAttack2 ( float flDot, float flDist ) { // if the grunt isn't moving, it's ok to check. if ( m_flGroundSpeed != 0 ) { m_fThrowGrenade = FALSE; return m_fThrowGrenade; } // assume things haven't changed too much since last time if (gpGlobals->time < m_flNextGrenadeCheck ) { return m_fThrowGrenade; } if ( !FBitSet ( m_hEnemy->pev->flags, FL_ONGROUND ) && m_hEnemy->pev->waterlevel == 0 && m_vecEnemyLKP.z > pev->absmax.z ) { //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to // be grenaded. // don't throw grenades at anything that isn't on the ground! m_fThrowGrenade = FALSE; return m_fThrowGrenade; } Vector vecTarget; // find feet if (RANDOM_LONG(0,1)) { // magically know where they are vecTarget = Vector( m_hEnemy->pev->origin.x, m_hEnemy->pev->origin.y, m_hEnemy->pev->absmin.z ); } else { // toss it to where you last saw them vecTarget = m_vecEnemyLKP; } // vecTarget = m_vecEnemyLKP + (m_hEnemy->BodyTarget( pev->origin ) - m_hEnemy->pev->origin); // estimate position // vecTarget = vecTarget + m_hEnemy->pev->velocity * 2; if ( ( vecTarget - pev->origin ).Length2D() <= 256 ) { // crap, I don't want to blow myself up m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. m_fThrowGrenade = FALSE; return m_fThrowGrenade; } Vector vecToss = VecCheckToss( pev, GetGunPosition(), vecTarget, 0.5 ); if ( vecToss != g_vecZero ) { m_vecTossVelocity = vecToss; // throw a hand grenade m_fThrowGrenade = TRUE; // don't check again for a while. m_flNextGrenadeCheck = gpGlobals->time; // 1/3 second. } else { // don't throw m_fThrowGrenade = FALSE; // don't check again for a while. m_flNextGrenadeCheck = gpGlobals->time + 1; // one full second. } return m_fThrowGrenade; }