Fixed monster turn rate being too slow.
Fixed heavy weapons grunt AI being complete nonsense. Small improvements to stukabat.
This commit is contained in:
@@ -156,11 +156,11 @@ Doing this will free **85** sounds from the precache list that you can now use f
|
|||||||
|
|
||||||
I'm aware that the plugin is far from perfect, and there are a few things that need polishing *-especially the AI-*. I'll try to fix/will be fixing as the project evolves:
|
I'm aware that the plugin is far from perfect, and there are a few things that need polishing *-especially the AI-*. I'll try to fix/will be fixing as the project evolves:
|
||||||
|
|
||||||
- The Heavy Weapons Grunt AI is borked, they "run" with their miniguns like if they have pistols.
|
- Rarely, Stukabats will become unable to fly towards their target, standing in air doing seemingly nothing. Cause of bug unknown.
|
||||||
|
|
||||||
- Monster "turning speed" (yaw speed) is too slow. While this doesn't cause any breaks, it degrades the quality of the AI, making them really easy to cheese.
|
- Entvars are not recognized, so anything that is a pevfield that is not used by monstermod is unusable.
|
||||||
|
|
||||||
There are probably more issues that aren't listed here, I'll attempt to fix them as I find them. Of course, any bug report is welcome.
|
There are probably more issues that aren't listed here, I'll attempt to fix them as I find them. Of course, any bug report is welcome. If reporting a bug, try to explain step by step how the bug ocurred. The easier it is to replicate a bug, the easier it is to locate it and fix it.
|
||||||
|
|
||||||
## Milestones
|
## Milestones
|
||||||
|
|
||||||
|
|||||||
@@ -1085,7 +1085,7 @@ jlb*/
|
|||||||
{
|
{
|
||||||
m_movementActivity = ACT_FLY;
|
m_movementActivity = ACT_FLY;
|
||||||
}
|
}
|
||||||
if ( LookupActivity( ACT_WALK ) != ACTIVITY_NOT_AVAILABLE )
|
else if ( LookupActivity( ACT_WALK ) != ACTIVITY_NOT_AVAILABLE )
|
||||||
{
|
{
|
||||||
m_movementActivity = ACT_WALK;
|
m_movementActivity = ACT_WALK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ public:
|
|||||||
|
|
||||||
string_t m_szMonsterName; // Monster name to display on HUD
|
string_t m_szMonsterName; // Monster name to display on HUD
|
||||||
int m_iClassifyOverride; // Overriden classification for this monster
|
int m_iClassifyOverride; // Overriden classification for this monster
|
||||||
|
float m_flLastYawTime;
|
||||||
|
|
||||||
void KeyValue( KeyValueData *pkvd );
|
void KeyValue( KeyValueData *pkvd );
|
||||||
|
|
||||||
@@ -1667,8 +1668,6 @@ public:
|
|||||||
void Minigun(void);
|
void Minigun(void);
|
||||||
|
|
||||||
CUSTOM_SCHEDULES
|
CUSTOM_SCHEDULES
|
||||||
|
|
||||||
float m_flMinigunSpinTime;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|||||||
@@ -32,46 +32,38 @@
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
// monster-specific DEFINE's
|
// monster-specific DEFINE's
|
||||||
//=========================================================
|
//=========================================================
|
||||||
#define HWGRUNT_9MM_CLIP_SIZE 17 // clip ammo per gun
|
|
||||||
#define HWGRUNT_DGL_CLIP_SIZE 7
|
|
||||||
#define HWGRUNT_357_CLIP_SIZE 6
|
|
||||||
|
|
||||||
// Weapon flags
|
// Weapon flags
|
||||||
#define HWGRUNT_MINIGUN 0
|
#define HWGRUNT_MINIGUN 0
|
||||||
#define HWGRUNT_PISTOL_9MM 1
|
|
||||||
#define HWGRUNT_PISTOL_DGL 2
|
|
||||||
#define HWGRUNT_PISTOL_357 3
|
|
||||||
|
|
||||||
#define GUN_GROUP 1
|
#define GUN_GROUP 1
|
||||||
|
|
||||||
// Gun values
|
// Gun values
|
||||||
#define GUN_MINIGUN 0
|
#define GUN_MINIGUN 0
|
||||||
#define GUN_PISTOL_9MM 1
|
|
||||||
#define GUN_PISTOL_357 2
|
|
||||||
#define GUN_PISTOL_DGL 3
|
|
||||||
#define GUN_NONE 4
|
|
||||||
|
|
||||||
//=========================================================
|
|
||||||
// Monster's Anim Events Go Here
|
|
||||||
//=========================================================
|
|
||||||
#define HWGRUNT_AE_DEATH ( 11 )
|
|
||||||
#define HWGRUNT_AE_MINIGUN ( 5001 )
|
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// monster-specific schedule types
|
// monster-specific schedule types
|
||||||
//=========================================================
|
//=========================================================
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
SCHED_HWGRUNT_SUPPRESS = LAST_COMMON_SCHEDULE + 1,
|
SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE = LAST_COMMON_SCHEDULE + 1,// move to a location to set up an attack against the enemy.
|
||||||
SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE,// move to a location to set up an attack against the enemy. (usually when a friendly is in the way).
|
|
||||||
SCHED_HWGRUNT_SWEEP,
|
|
||||||
SCHED_HWGRUNT_REPEL,
|
SCHED_HWGRUNT_REPEL,
|
||||||
SCHED_HWGRUNT_REPEL_ATTACK,
|
|
||||||
SCHED_HWGRUNT_REPEL_LAND,
|
SCHED_HWGRUNT_REPEL_LAND,
|
||||||
SCHED_HWGRUNT_WAIT_FACE_ENEMY,
|
SCHED_HWGRUNT_WAIT_FACE_ENEMY,
|
||||||
|
SCHED_HWGRUNT_TAKECOVER_FAILED,// force analysis of conditions and pick the best possible schedule to recover from failure.
|
||||||
SCHED_HWGRUNT_ELOF_FAIL,
|
SCHED_HWGRUNT_ELOF_FAIL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// monster-specific conditions
|
||||||
|
//=========================================================
|
||||||
|
#define bits_MEMORY_HWGRUNT_SPINUP ( bits_MEMORY_CUSTOM1 )
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// Monster's Anim Events Go Here
|
||||||
|
//=========================================================
|
||||||
|
#define HWGRUNT_AE_DEATH ( 11 )
|
||||||
|
#define HWGRUNT_AE_MINIGUN ( 5001 )
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// Classify - indicates this monster's place in the
|
// Classify - indicates this monster's place in the
|
||||||
// relationship table.
|
// relationship table.
|
||||||
@@ -214,7 +206,7 @@ void CMHWGrunt::Spawn()
|
|||||||
m_MonsterState = MONSTERSTATE_NONE;
|
m_MonsterState = MONSTERSTATE_NONE;
|
||||||
//m_flNextGrenadeCheck = gpGlobals->time + 1;
|
//m_flNextGrenadeCheck = gpGlobals->time + 1;
|
||||||
m_flNextPainTime = gpGlobals->time;
|
m_flNextPainTime = gpGlobals->time;
|
||||||
m_flMinigunSpinTime = 0; // be able to spin up/down minigun right away
|
//m_flMinigunSpinTime = 0; // be able to spin up/down minigun right away
|
||||||
m_iSentence = -1;
|
m_iSentence = -1;
|
||||||
m_fStanding = TRUE;
|
m_fStanding = TRUE;
|
||||||
|
|
||||||
@@ -260,13 +252,14 @@ void CMHWGrunt::Precache()
|
|||||||
PRECACHE_SOUND("hassault/hw_spinup.wav");
|
PRECACHE_SOUND("hassault/hw_spinup.wav");
|
||||||
PRECACHE_SOUND("hassault/hw_spindown.wav");
|
PRECACHE_SOUND("hassault/hw_spindown.wav");
|
||||||
|
|
||||||
PRECACHE_SOUND("common/null.wav");
|
|
||||||
|
|
||||||
// get voice pitch
|
// get voice pitch
|
||||||
if (RANDOM_LONG(0, 1))
|
if (RANDOM_LONG(0, 1))
|
||||||
m_voicePitch = 102 + RANDOM_LONG(0, 7);
|
m_voicePitch = 102 + RANDOM_LONG(0, 7);
|
||||||
else
|
else
|
||||||
m_voicePitch = 93; // slight voice change for hwgrunt
|
m_voicePitch = 93; // slight voice change for hwgrunt
|
||||||
|
|
||||||
|
CMHGrunt hgrunt;
|
||||||
|
hgrunt.Precache();
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
@@ -274,7 +267,7 @@ void CMHWGrunt::Precache()
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// GruntFail
|
// Fail
|
||||||
//=========================================================
|
//=========================================================
|
||||||
Task_t tlHWGruntFail[] =
|
Task_t tlHWGruntFail[] =
|
||||||
{
|
{
|
||||||
@@ -296,7 +289,7 @@ Schedule_t slHWGruntFail[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// Grunt Combat Fail
|
// Combat Fail
|
||||||
//=========================================================
|
//=========================================================
|
||||||
Task_t tlHWGruntCombatFail[] =
|
Task_t tlHWGruntCombatFail[] =
|
||||||
{
|
{
|
||||||
@@ -318,7 +311,7 @@ Schedule_t slHWGruntCombatFail[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// Victory dance!
|
// Not really victory dance
|
||||||
//=========================================================
|
//=========================================================
|
||||||
Task_t tlHWGruntVictoryDance[] =
|
Task_t tlHWGruntVictoryDance[] =
|
||||||
{
|
{
|
||||||
@@ -328,7 +321,8 @@ Task_t tlHWGruntVictoryDance[] =
|
|||||||
{ TASK_GET_PATH_TO_ENEMY_CORPSE, (float)0 },
|
{ TASK_GET_PATH_TO_ENEMY_CORPSE, (float)0 },
|
||||||
{ TASK_WALK_PATH, (float)0 },
|
{ TASK_WALK_PATH, (float)0 },
|
||||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
{ TASK_FACE_ENEMY, (float)0 }
|
{ TASK_FACE_ENEMY, (float)0 },
|
||||||
|
// { TASK_PLAY_SEQUENCE, (float)ACT_VICTORY_DANCE },
|
||||||
};
|
};
|
||||||
|
|
||||||
Schedule_t slHWGruntVictoryDance[] =
|
Schedule_t slHWGruntVictoryDance[] =
|
||||||
@@ -336,38 +330,14 @@ Schedule_t slHWGruntVictoryDance[] =
|
|||||||
{
|
{
|
||||||
tlHWGruntVictoryDance,
|
tlHWGruntVictoryDance,
|
||||||
ARRAYSIZE ( tlHWGruntVictoryDance ),
|
ARRAYSIZE ( tlHWGruntVictoryDance ),
|
||||||
bits_COND_NEW_ENEMY,
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_LIGHT_DAMAGE |
|
||||||
|
bits_COND_HEAVY_DAMAGE,
|
||||||
0,
|
0,
|
||||||
"HWGrunt Victory Dance"
|
"HWGrunt Victory Dance"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
|
||||||
// ELOF fail, just wait and try again
|
|
||||||
//=========================================================
|
|
||||||
Task_t tlHWGruntELOFFail[] =
|
|
||||||
{
|
|
||||||
{ TASK_STOP_MOVING, (float)0 },
|
|
||||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_WAIT, (float)1.5 },
|
|
||||||
{ TASK_SET_SCHEDULE, (float)SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE },
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule_t slHWGruntELOFFail[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tlHWGruntELOFFail,
|
|
||||||
ARRAYSIZE ( tlHWGruntELOFFail ),
|
|
||||||
bits_COND_NEW_ENEMY |
|
|
||||||
bits_COND_ENEMY_DEAD |
|
|
||||||
bits_COND_CAN_RANGE_ATTACK1,
|
|
||||||
0,
|
|
||||||
"HWGrunt Failed ELOF"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// Establish line of fire - move to a position that allows
|
// Establish line of fire - move to a position that allows
|
||||||
// the grunt to attack.
|
// the grunt to attack.
|
||||||
@@ -376,6 +346,7 @@ Task_t tlHWGruntEstablishLineOfFire[] =
|
|||||||
{
|
{
|
||||||
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_HWGRUNT_ELOF_FAIL },
|
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_HWGRUNT_ELOF_FAIL },
|
||||||
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
|
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
|
||||||
|
// { TASK_GRUNT_SPEAK_SENTENCE,(float)0 },
|
||||||
{ TASK_RUN_PATH, (float)0 },
|
{ TASK_RUN_PATH, (float)0 },
|
||||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
};
|
};
|
||||||
@@ -395,61 +366,9 @@ Schedule_t slHWGruntEstablishLineOfFire[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// GruntCombatFace Schedule
|
// wait in cover - we don't allow danger or the ability to
|
||||||
//=========================================================
|
// attack to break a grunt's run to cover schedule, but when
|
||||||
Task_t tlHWGruntCombatFace1[] =
|
// a grunt is in cover, we do want them to attack if they can.
|
||||||
{
|
|
||||||
{ TASK_STOP_MOVING, 0 },
|
|
||||||
{ TASK_SET_ACTIVITY, (float)ACT_IDLE },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_WAIT, (float)1.5 },
|
|
||||||
{ TASK_SET_SCHEDULE, (float)SCHED_HWGRUNT_SWEEP },
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule_t slHWGruntCombatFace[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tlHWGruntCombatFace1,
|
|
||||||
ARRAYSIZE ( tlHWGruntCombatFace1 ),
|
|
||||||
bits_COND_NEW_ENEMY |
|
|
||||||
bits_COND_ENEMY_DEAD |
|
|
||||||
bits_COND_CAN_RANGE_ATTACK1,
|
|
||||||
0,
|
|
||||||
"HWCombat Face"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Task_t tlHWGruntSuppress[] =
|
|
||||||
{
|
|
||||||
{ TASK_STOP_MOVING, 0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule_t slHWGruntSuppress[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tlHWGruntSuppress,
|
|
||||||
ARRAYSIZE ( tlHWGruntSuppress ),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
"HWSuppress"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
|
||||||
// grunt wait in cover - we don't allow danger or the ability
|
|
||||||
// to attack to break a grunt's run to cover schedule, but
|
|
||||||
// when a grunt is in cover, we do want them to attack if they can.
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
Task_t tlHWGruntWaitInCover[] =
|
Task_t tlHWGruntWaitInCover[] =
|
||||||
{
|
{
|
||||||
@@ -471,61 +390,78 @@ Schedule_t slHWGruntWaitInCover[] =
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// Do a turning sweep of the area
|
// run to cover.
|
||||||
//=========================================================
|
//=========================================================
|
||||||
Task_t tlHWGruntSweep[] =
|
Task_t tlHWGruntTakeCover[] =
|
||||||
{
|
|
||||||
{ TASK_TURN_LEFT, (float)179 },
|
|
||||||
{ TASK_WAIT, (float)1 },
|
|
||||||
{ TASK_TURN_LEFT, (float)179 },
|
|
||||||
{ TASK_WAIT, (float)1 },
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule_t slHWGruntSweep[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tlHWGruntSweep,
|
|
||||||
ARRAYSIZE ( tlHWGruntSweep ),
|
|
||||||
bits_COND_NEW_ENEMY |
|
|
||||||
bits_COND_CAN_RANGE_ATTACK1,
|
|
||||||
0,
|
|
||||||
"HWGrunt Sweep"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
|
||||||
// primary range attack. Overriden because base class stops attacking when the enemy is occluded.
|
|
||||||
// grunt's grenade toss requires the enemy be occluded.
|
|
||||||
//=========================================================
|
|
||||||
Task_t tlHWGruntRangeAttack1B[] =
|
|
||||||
{
|
{
|
||||||
{ TASK_STOP_MOVING, (float)0 },
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
{ TASK_PLAY_SEQUENCE_FACE_ENEMY,(float)ACT_IDLE_ANGRY },
|
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_HWGRUNT_TAKECOVER_FAILED },
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
{ TASK_WAIT, (float)0.2 },
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
// { TASK_GRUNT_SPEAK_SENTENCE, (float)0 },
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
{ TASK_RUN_PATH, (float)0 },
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||||
{ TASK_RANGE_ATTACK1, (float)0 },
|
{ TASK_SET_SCHEDULE, (float)SCHED_HWGRUNT_WAIT_FACE_ENEMY },
|
||||||
};
|
};
|
||||||
|
|
||||||
Schedule_t slHWGruntRangeAttack1B[] =
|
Schedule_t slHWGruntTakeCover[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
tlHWGruntRangeAttack1B,
|
tlHWGruntTakeCover,
|
||||||
ARRAYSIZE ( tlHWGruntRangeAttack1B ),
|
ARRAYSIZE ( tlHWGruntTakeCover ),
|
||||||
bits_COND_NEW_ENEMY |
|
|
||||||
bits_COND_ENEMY_DEAD |
|
|
||||||
bits_COND_ENEMY_OCCLUDED,
|
|
||||||
0,
|
0,
|
||||||
"HWRange Attack1B"
|
0,
|
||||||
|
"HWGrunt Take Cover"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// minigun spinup
|
||||||
|
//=========================================================
|
||||||
|
Task_t tlHWGruntMinigunSpinUp[] =
|
||||||
|
{
|
||||||
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
|
{ TASK_SET_ACTIVITY, (float)ACT_THREAT_DISPLAY },
|
||||||
|
{ TASK_WAIT_FACE_ENEMY, (float)1 },
|
||||||
|
{ TASK_REMEMBER, (float)bits_MEMORY_HWGRUNT_SPINUP },
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule_t slHWGruntMinigunSpinUp[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
tlHWGruntMinigunSpinUp,
|
||||||
|
ARRAYSIZE ( tlHWGruntMinigunSpinUp ),
|
||||||
|
0, // nothing should interrupt this
|
||||||
|
0,
|
||||||
|
"HWGrunt Minigun Spin Up"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// minigun attack
|
||||||
|
//=========================================================
|
||||||
|
Task_t tlHWGruntMinigunAttack[] =
|
||||||
|
{
|
||||||
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
|
{ TASK_PLAY_SEQUENCE_FACE_ENEMY, (float)ACT_RANGE_ATTACK1 },
|
||||||
|
{ TASK_RANGE_ATTACK1, (float)0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule_t slHWGruntMinigunAttack[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
tlHWGruntMinigunAttack,
|
||||||
|
ARRAYSIZE ( tlHWGruntMinigunAttack ),
|
||||||
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_ENEMY_DEAD |
|
||||||
|
bits_COND_ENEMY_OCCLUDED |
|
||||||
|
bits_COND_HEAR_SOUND,
|
||||||
|
0,
|
||||||
|
"HWGrunt Minigun Attack"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// repel
|
// repel
|
||||||
@@ -543,31 +479,12 @@ Schedule_t slHWGruntRepel[] =
|
|||||||
tlHWGruntRepel,
|
tlHWGruntRepel,
|
||||||
ARRAYSIZE ( tlHWGruntRepel ),
|
ARRAYSIZE ( tlHWGruntRepel ),
|
||||||
bits_COND_SEE_ENEMY |
|
bits_COND_SEE_ENEMY |
|
||||||
bits_COND_NEW_ENEMY,
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_LIGHT_DAMAGE |
|
||||||
|
bits_COND_HEAVY_DAMAGE |
|
||||||
|
bits_COND_HEAR_SOUND,
|
||||||
0,
|
0,
|
||||||
"HWRepel"
|
"HWGrunt Repel"
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
|
||||||
// repel
|
|
||||||
//=========================================================
|
|
||||||
Task_t tlHWGruntRepelAttack[] =
|
|
||||||
{
|
|
||||||
{ TASK_STOP_MOVING, (float)0 },
|
|
||||||
{ TASK_FACE_ENEMY, (float)0 },
|
|
||||||
{ TASK_PLAY_SEQUENCE, (float)ACT_FLY },
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule_t slHWGruntRepelAttack[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tlHWGruntRepelAttack,
|
|
||||||
ARRAYSIZE ( tlHWGruntRepelAttack ),
|
|
||||||
bits_COND_ENEMY_OCCLUDED,
|
|
||||||
0,
|
|
||||||
"HWRepel Attack"
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -590,9 +507,41 @@ Schedule_t slHWGruntRepelLand[] =
|
|||||||
tlHWGruntRepelLand,
|
tlHWGruntRepelLand,
|
||||||
ARRAYSIZE ( tlHWGruntRepelLand ),
|
ARRAYSIZE ( tlHWGruntRepelLand ),
|
||||||
bits_COND_SEE_ENEMY |
|
bits_COND_SEE_ENEMY |
|
||||||
bits_COND_NEW_ENEMY,
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_LIGHT_DAMAGE |
|
||||||
|
bits_COND_HEAVY_DAMAGE |
|
||||||
|
bits_COND_HEAR_SOUND,
|
||||||
0,
|
0,
|
||||||
"HWRepel Land"
|
"HWGrunt Repel Land"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// Chase enemy failure
|
||||||
|
//=========================================================
|
||||||
|
Task_t tlHWGruntChaseEnemyFailed[] =
|
||||||
|
{
|
||||||
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
|
{ TASK_WAIT, (float)0.2 },
|
||||||
|
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
|
||||||
|
{ TASK_RUN_PATH, (float)0 },
|
||||||
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
|
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||||
|
// { TASK_TURN_LEFT, (float)179 },
|
||||||
|
{ TASK_FACE_ENEMY, (float)0 },
|
||||||
|
{ TASK_WAIT, (float)1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule_t slHWGruntChaseEnemyFailed[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
tlHWGruntChaseEnemyFailed,
|
||||||
|
ARRAYSIZE ( tlHWGruntChaseEnemyFailed ),
|
||||||
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_CAN_RANGE_ATTACK1 |
|
||||||
|
bits_COND_HEAR_SOUND,
|
||||||
|
0,
|
||||||
|
"HWGrunt Chase Enemy Failed"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -602,121 +551,43 @@ DEFINE_CUSTOM_SCHEDULES( CMHWGrunt )
|
|||||||
slHWGruntFail,
|
slHWGruntFail,
|
||||||
slHWGruntCombatFail,
|
slHWGruntCombatFail,
|
||||||
slHWGruntVictoryDance,
|
slHWGruntVictoryDance,
|
||||||
slHWGruntELOFFail,
|
|
||||||
slHWGruntEstablishLineOfFire,
|
slHWGruntEstablishLineOfFire,
|
||||||
slHWGruntCombatFace,
|
|
||||||
slHWGruntSuppress,
|
|
||||||
slHWGruntWaitInCover,
|
slHWGruntWaitInCover,
|
||||||
slHWGruntSweep,
|
slHWGruntTakeCover,
|
||||||
slHWGruntRangeAttack1B,
|
slHWGruntMinigunSpinUp,
|
||||||
|
slHWGruntMinigunAttack,
|
||||||
slHWGruntRepel,
|
slHWGruntRepel,
|
||||||
slHWGruntRepelAttack,
|
|
||||||
slHWGruntRepelLand,
|
slHWGruntRepelLand,
|
||||||
|
slHWGruntChaseEnemyFailed,
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_CUSTOM_SCHEDULES( CMHWGrunt, CMBaseMonster );
|
IMPLEMENT_CUSTOM_SCHEDULES( CMHWGrunt, CMBaseMonster );
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
// SetActivity - different set than normal hgrunt, adapt
|
// SetActivity
|
||||||
//=========================================================
|
//=========================================================
|
||||||
void CMHWGrunt :: SetActivity ( Activity NewActivity )
|
void CMHWGrunt :: SetActivity ( Activity NewActivity )
|
||||||
{
|
{
|
||||||
int iSequence = ACTIVITY_NOT_AVAILABLE;
|
int iSequence = ACTIVITY_NOT_AVAILABLE;
|
||||||
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
void *pmodel = GET_MODEL_PTR( ENT(pev) );
|
||||||
bool refreshActivity = TRUE;
|
|
||||||
|
|
||||||
// PS: This is terrible code. -Giegue
|
|
||||||
|
|
||||||
// Time to die?
|
|
||||||
if ( NewActivity < ACT_DIESIMPLE )
|
|
||||||
{
|
|
||||||
if ( pev->sequence == LookupSequence( "attack" ) )
|
|
||||||
{
|
|
||||||
// I won't do anything else if I'm attacking!
|
|
||||||
refreshActivity = FALSE;
|
|
||||||
|
|
||||||
// Unless the enemy has gone out of my sight
|
|
||||||
if ( m_hEnemy == 0 || !UTIL_IsAlive( m_hEnemy ) || !UTIL_FVisible( m_hEnemy, ENT(pev) ) )
|
|
||||||
{
|
|
||||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
|
|
||||||
m_flMinigunSpinTime = gpGlobals->time + 1.40;
|
|
||||||
iSequence = LookupSequence( "spindown" ); // time to relax
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( pev->sequence == LookupSequence( "spindown" ) )
|
|
||||||
{
|
|
||||||
// Not yet!
|
|
||||||
refreshActivity = FALSE;
|
|
||||||
|
|
||||||
// Wait until the minigun is no longer spinning before doing something else
|
|
||||||
if ( gpGlobals->time > m_flMinigunSpinTime )
|
|
||||||
{
|
|
||||||
refreshActivity = TRUE;
|
|
||||||
m_flMinigunSpinTime = 0; // do spin up again when required
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refreshActivity)
|
|
||||||
{
|
|
||||||
switch ( NewActivity )
|
switch ( NewActivity )
|
||||||
{
|
{
|
||||||
case ACT_RANGE_ATTACK1:
|
case ACT_RANGE_ATTACK1:
|
||||||
// if carring a gun, either standing or crouched.
|
|
||||||
// always standing when firing minigun
|
|
||||||
if (pev->weapons > 0) // any pistol
|
|
||||||
{
|
|
||||||
// same animation regardless of pistol
|
|
||||||
if ( m_fStanding )
|
|
||||||
{
|
|
||||||
// get aimable sequence
|
|
||||||
iSequence = LookupSequence( "pistol_shoot" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// get crouching shoot
|
|
||||||
iSequence = LookupSequence( "pistol_crouchshoot" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // minigun
|
|
||||||
{
|
|
||||||
if ( m_flMinigunSpinTime == 0 ) // starting to spin up the minigun
|
|
||||||
{
|
|
||||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hassault/hw_spinup.wav", 0.8, ATTN_NORM);
|
|
||||||
m_flMinigunSpinTime = gpGlobals->time + 1.15;
|
|
||||||
iSequence = LookupSequence( "spinup" );
|
|
||||||
}
|
|
||||||
else if ( gpGlobals->time > m_flMinigunSpinTime ) // spun up, ready to fire
|
|
||||||
iSequence = LookupSequence( "attack" );
|
iSequence = LookupSequence( "attack" );
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ACT_IDLE:
|
|
||||||
if ( m_MonsterState == MONSTERSTATE_COMBAT )
|
|
||||||
{
|
|
||||||
NewActivity = ACT_IDLE_ANGRY;
|
|
||||||
}
|
|
||||||
iSequence = LookupActivity ( NewActivity );
|
|
||||||
break;
|
break;
|
||||||
case ACT_RUN:
|
case ACT_RUN:
|
||||||
|
iSequence = LookupSequence( "run" );
|
||||||
|
break;
|
||||||
case ACT_WALK:
|
case ACT_WALK:
|
||||||
|
iSequence = LookupSequence( "creeping_walk" );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if ( m_flMinigunSpinTime != 0 )
|
|
||||||
{
|
|
||||||
// if the hwgrunt used his minigun but became unable to attack
|
|
||||||
// then spin it down before doing anything else
|
|
||||||
refreshActivity = FALSE;
|
|
||||||
|
|
||||||
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
|
|
||||||
m_flMinigunSpinTime = gpGlobals->time + 1.40;
|
|
||||||
iSequence = LookupSequence( "spindown" );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
iSequence = LookupActivity( NewActivity );
|
iSequence = LookupActivity( NewActivity );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
|
m_Activity = NewActivity; // Go ahead and set this so it doesn't keep trying when the anim is not present
|
||||||
}
|
|
||||||
|
|
||||||
// Set to the desired anim, or default anim if the desired is not present
|
// Set to the desired anim, or default anim if the desired is not present
|
||||||
if ( iSequence > ACTIVITY_NOT_AVAILABLE )
|
if ( iSequence > ACTIVITY_NOT_AVAILABLE )
|
||||||
@@ -730,7 +601,7 @@ void CMHWGrunt :: SetActivity ( Activity NewActivity )
|
|||||||
ResetSequenceInfo( );
|
ResetSequenceInfo( );
|
||||||
SetYawSpeed();
|
SetYawSpeed();
|
||||||
}
|
}
|
||||||
else if (refreshActivity)
|
else
|
||||||
{
|
{
|
||||||
// Not available try to get default anim
|
// Not available try to get default anim
|
||||||
ALERT ( at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity );
|
ALERT ( at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity );
|
||||||
@@ -743,6 +614,9 @@ void CMHWGrunt :: SetActivity ( Activity NewActivity )
|
|||||||
//=========================================================
|
//=========================================================
|
||||||
Schedule_t *CMHWGrunt :: GetSchedule( void )
|
Schedule_t *CMHWGrunt :: GetSchedule( void )
|
||||||
{
|
{
|
||||||
|
// clear old sentence
|
||||||
|
m_iSentence = -1; // we don't care about sounds for now.
|
||||||
|
|
||||||
// flying? If PRONE, barnacle has me. IF not, it's assumed I am rapelling.
|
// flying? If PRONE, barnacle has me. IF not, it's assumed I am rapelling.
|
||||||
if ( pev->movetype == MOVETYPE_FLY && m_MonsterState != MONSTERSTATE_PRONE )
|
if ( pev->movetype == MOVETYPE_FLY && m_MonsterState != MONSTERSTATE_PRONE )
|
||||||
{
|
{
|
||||||
@@ -754,10 +628,7 @@ Schedule_t *CMHWGrunt :: GetSchedule( void )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// repel down a rope,
|
// can not attack while holding a minigun in rapel
|
||||||
if ( m_MonsterState == MONSTERSTATE_COMBAT )
|
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_REPEL_ATTACK );
|
|
||||||
else
|
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_REPEL );
|
return GetScheduleOfType ( SCHED_HWGRUNT_REPEL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,6 +640,13 @@ Schedule_t *CMHWGrunt :: GetSchedule( void )
|
|||||||
// dead enemy
|
// dead enemy
|
||||||
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
if ( HasConditions( bits_COND_ENEMY_DEAD ) )
|
||||||
{
|
{
|
||||||
|
// was attacking, spin down
|
||||||
|
if ( HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
|
||||||
|
{
|
||||||
|
Forget( bits_MEMORY_HWGRUNT_SPINUP );
|
||||||
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
|
||||||
|
}
|
||||||
|
|
||||||
// call base class, all code to handle dead enemies is centralized there.
|
// call base class, all code to handle dead enemies is centralized there.
|
||||||
return CMBaseMonster :: GetSchedule();
|
return CMBaseMonster :: GetSchedule();
|
||||||
}
|
}
|
||||||
@@ -776,36 +654,72 @@ Schedule_t *CMHWGrunt :: GetSchedule( void )
|
|||||||
// new enemy
|
// new enemy
|
||||||
if ( HasConditions(bits_COND_NEW_ENEMY) )
|
if ( HasConditions(bits_COND_NEW_ENEMY) )
|
||||||
{
|
{
|
||||||
|
// none of this should take place as CSquadMonster functions were completely stripped. -Giegue
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
{
|
||||||
|
//!!!KELLY - the leader of a squad of grunts has just seen the player or a
|
||||||
|
// monster and has made it the squad's enemy. You
|
||||||
|
// can check pev->flags for FL_CLIENT to determine whether this is the player
|
||||||
|
// or a monster. He's going to immediately start
|
||||||
|
// firing, though. If you'd like, we can make an alternate "first sight"
|
||||||
|
// schedule where the leader plays a handsign anim
|
||||||
|
// that gives us enough time to hear a short sentence or spoken command
|
||||||
|
// before he starts pluggin away.
|
||||||
|
if (FOkToSpeak())// && RANDOM_LONG(0,1))
|
||||||
|
{
|
||||||
|
if ((m_hEnemy != NULL) && UTIL_IsPlayer(m_hEnemy))
|
||||||
|
// player
|
||||||
|
SENTENCEG_PlayRndSz( ENT(pev), "HG_ALERT", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch);
|
||||||
|
|
||||||
|
else if ((m_hEnemy != NULL) &&
|
||||||
|
(m_hEnemy->Classify() != CLASS_PLAYER_ALLY) &&
|
||||||
|
(m_hEnemy->Classify() != CLASS_HUMAN_PASSIVE) &&
|
||||||
|
(m_hEnemy->Classify() != CLASS_MACHINE))
|
||||||
|
// monster
|
||||||
|
SENTENCEG_PlayRndSz( ENT(pev), "HG_MONST", HGRUNT_SENTENCE_VOLUME, GRUNT_ATTN, 0, m_voicePitch);
|
||||||
|
|
||||||
|
JustSpoke();
|
||||||
|
}
|
||||||
|
|
||||||
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
||||||
{
|
{
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_SUPPRESS );
|
return GetScheduleOfType ( SCHED_GRUNT_SUPPRESS );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE );
|
return GetScheduleOfType ( SCHED_GRUNT_ESTABLISH_LINE_OF_FIRE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no ammo
|
}
|
||||||
else if ( HasConditions ( bits_COND_NO_AMMO_LOADED ) )
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// damaged just a little
|
||||||
|
else if ( HasConditions( bits_COND_LIGHT_DAMAGE ) )
|
||||||
{
|
{
|
||||||
// Stop believing you have no ammo! -Giegue
|
// we don't want the monster to take cover when hurt while attacking, clear this
|
||||||
ClearConditions( bits_COND_NO_AMMO_LOADED );
|
ClearConditions( bits_COND_LIGHT_DAMAGE );
|
||||||
if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
|
||||||
{
|
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_SUPPRESS );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// can shoot
|
// can shoot
|
||||||
else if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
else if ( HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
||||||
{
|
{
|
||||||
// Force attack!
|
// can fire? shoot. destroy without a care
|
||||||
return GetScheduleOfType ( SCHED_HWGRUNT_SUPPRESS );
|
return GetScheduleOfType( SCHED_RANGE_ATTACK1 );
|
||||||
}
|
}
|
||||||
// can't see enemy
|
// can't see enemy
|
||||||
|
else if ( HasConditions( bits_COND_ENEMY_OCCLUDED ) )
|
||||||
|
{
|
||||||
|
// do sound
|
||||||
|
if ( HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
|
||||||
|
{
|
||||||
|
Forget( bits_MEMORY_HWGRUNT_SPINUP );
|
||||||
|
EMIT_SOUND(ENT(pev), CHAN_ITEM, "hassault/hw_spindown.wav", 0.8, ATTN_NORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then go kamikaze and chase the enemy
|
||||||
|
return GetScheduleOfType( SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE );
|
||||||
|
}
|
||||||
|
|
||||||
if ( HasConditions( bits_COND_SEE_ENEMY ) && !HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
if ( HasConditions( bits_COND_SEE_ENEMY ) && !HasConditions ( bits_COND_CAN_RANGE_ATTACK1 ) )
|
||||||
{
|
{
|
||||||
@@ -824,10 +738,24 @@ Schedule_t* CMHWGrunt :: GetScheduleOfType ( int Type )
|
|||||||
{
|
{
|
||||||
switch ( Type )
|
switch ( Type )
|
||||||
{
|
{
|
||||||
|
case SCHED_TAKE_COVER_FROM_ENEMY:
|
||||||
|
{
|
||||||
|
return &slHWGruntTakeCover[ 0 ];
|
||||||
|
}
|
||||||
|
case SCHED_HWGRUNT_TAKECOVER_FAILED:
|
||||||
|
{
|
||||||
|
if ( HasConditions( bits_COND_CAN_RANGE_ATTACK1 ) )
|
||||||
|
{
|
||||||
|
return GetScheduleOfType( SCHED_RANGE_ATTACK1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetScheduleOfType ( SCHED_FAIL );
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SCHED_HWGRUNT_ELOF_FAIL:
|
case SCHED_HWGRUNT_ELOF_FAIL:
|
||||||
{
|
{
|
||||||
// human grunt is unable to move to a position that allows him to attack the enemy.
|
// unable to move to a position that allows attacking the enemy.
|
||||||
return &slHWGruntELOFFail[ 0 ];
|
return GetScheduleOfType ( SCHED_TAKE_COVER_FROM_ENEMY );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE:
|
case SCHED_HWGRUNT_ESTABLISH_LINE_OF_FIRE:
|
||||||
@@ -837,34 +765,28 @@ Schedule_t* CMHWGrunt :: GetScheduleOfType ( int Type )
|
|||||||
break;
|
break;
|
||||||
case SCHED_RANGE_ATTACK1:
|
case SCHED_RANGE_ATTACK1:
|
||||||
{
|
{
|
||||||
// no pistols yet, always do standing attack
|
// minigun should spin up first
|
||||||
return &slHWGruntRangeAttack1B[ 0 ];
|
if ( !HasMemory( bits_MEMORY_HWGRUNT_SPINUP ) )
|
||||||
}
|
|
||||||
case SCHED_COMBAT_FACE:
|
|
||||||
{
|
{
|
||||||
return &slHWGruntCombatFace[ 0 ];
|
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "hassault/hw_spinup.wav", 0.8, ATTN_NORM);
|
||||||
|
return &slHWGruntMinigunSpinUp[ 0 ];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return &slHWGruntMinigunAttack[ 0 ];
|
||||||
}
|
}
|
||||||
case SCHED_HWGRUNT_WAIT_FACE_ENEMY:
|
case SCHED_HWGRUNT_WAIT_FACE_ENEMY:
|
||||||
{
|
{
|
||||||
return &slHWGruntWaitInCover[ 0 ];
|
return &slHWGruntWaitInCover[ 0 ];
|
||||||
}
|
}
|
||||||
case SCHED_HWGRUNT_SWEEP:
|
|
||||||
{
|
|
||||||
return &slHWGruntSweep[ 0 ];
|
|
||||||
}
|
|
||||||
case SCHED_VICTORY_DANCE:
|
case SCHED_VICTORY_DANCE:
|
||||||
{
|
{
|
||||||
return &slHWGruntVictoryDance[ 0 ];
|
return &slHWGruntVictoryDance[ 0 ];
|
||||||
}
|
}
|
||||||
case SCHED_HWGRUNT_SUPPRESS:
|
|
||||||
{
|
|
||||||
return &slHWGruntSuppress[ 0 ];
|
|
||||||
}
|
|
||||||
case SCHED_FAIL:
|
case SCHED_FAIL:
|
||||||
{
|
{
|
||||||
if ( m_hEnemy != NULL )
|
if ( m_hEnemy != NULL )
|
||||||
{
|
{
|
||||||
// grunt has an enemy, so pick a different default fail schedule most likely to help recover.
|
// has an enemy, so pick a different default fail schedule most likely to help recover.
|
||||||
return &slHWGruntCombatFail[ 0 ];
|
return &slHWGruntCombatFail[ 0 ];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -876,19 +798,19 @@ Schedule_t* CMHWGrunt :: GetScheduleOfType ( int Type )
|
|||||||
pev->velocity.z -= 32;
|
pev->velocity.z -= 32;
|
||||||
return &slHWGruntRepel[ 0 ];
|
return &slHWGruntRepel[ 0 ];
|
||||||
}
|
}
|
||||||
case SCHED_HWGRUNT_REPEL_ATTACK:
|
|
||||||
{
|
|
||||||
if (pev->velocity.z > -128)
|
|
||||||
pev->velocity.z -= 32;
|
|
||||||
return &slHWGruntRepelAttack[ 0 ];
|
|
||||||
}
|
|
||||||
case SCHED_HWGRUNT_REPEL_LAND:
|
case SCHED_HWGRUNT_REPEL_LAND:
|
||||||
{
|
{
|
||||||
return &slHWGruntRepelLand[ 0 ];
|
return &slHWGruntRepelLand[ 0 ];
|
||||||
}
|
}
|
||||||
|
case SCHED_CHASE_ENEMY_FAILED:
|
||||||
|
{
|
||||||
|
// add missing schedule from squadmonster.cpp
|
||||||
|
return &slHWGruntChaseEnemyFailed[ 0 ];
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
return CMBaseMonster :: GetScheduleOfType ( Type );
|
return CMBaseMonster :: GetScheduleOfType ( Type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ cvar_t init_monster_show_deaths = {"monster_show_deaths", "1", FCVAR_EXTDLL, 0,
|
|||||||
cvar_t *monster_show_deaths = NULL;
|
cvar_t *monster_show_deaths = NULL;
|
||||||
cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL};
|
cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL};
|
||||||
cvar_t *monster_show_info = NULL;
|
cvar_t *monster_show_info = NULL;
|
||||||
|
cvar_t init_monster_turn_coeficient = {"monster_turn_coeficient", "1.75", FCVAR_EXTDLL, 0, NULL};
|
||||||
|
cvar_t *monster_turn_coeficient = NULL;
|
||||||
|
|
||||||
|
|
||||||
// Metamod requesting info about this plugin:
|
// Metamod requesting info about this plugin:
|
||||||
@@ -146,6 +148,9 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
|
|||||||
CVAR_REGISTER(&init_monster_show_info);
|
CVAR_REGISTER(&init_monster_show_info);
|
||||||
monster_show_info = CVAR_GET_POINTER("monster_show_info");
|
monster_show_info = CVAR_GET_POINTER("monster_show_info");
|
||||||
|
|
||||||
|
CVAR_REGISTER(&init_monster_turn_coeficient);
|
||||||
|
monster_turn_coeficient = CVAR_GET_POINTER("monster_turn_coeficient");
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ extern DLL_GLOBAL BOOL g_fDrawLines;
|
|||||||
|
|
||||||
extern CGraph WorldGraph;// the world node graph
|
extern CGraph WorldGraph;// the world node graph
|
||||||
|
|
||||||
|
extern cvar_t *monster_turn_coeficient;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
@@ -2234,7 +2236,22 @@ float CMBaseMonster::ChangeYaw ( int yawSpeed )
|
|||||||
ideal = pev->ideal_yaw;
|
ideal = pev->ideal_yaw;
|
||||||
if (current != ideal)
|
if (current != ideal)
|
||||||
{
|
{
|
||||||
speed = (float)yawSpeed * gpGlobals->frametime * 10;
|
// -SamVanheer
|
||||||
|
if ( m_flLastYawTime == 0 )
|
||||||
|
{
|
||||||
|
m_flLastYawTime = gpGlobals->time - gpGlobals->frametime;
|
||||||
|
}
|
||||||
|
|
||||||
|
float delta = gpGlobals->time - m_flLastYawTime;
|
||||||
|
if ( delta > 0.25 )
|
||||||
|
delta = 0.25;
|
||||||
|
|
||||||
|
// let server operators modify the multiplier coeficient -Giegue
|
||||||
|
float multiplier = monster_turn_coeficient->value;
|
||||||
|
if ( multiplier < 0.1 || multiplier > 10.0 )
|
||||||
|
multiplier = 1.75;
|
||||||
|
|
||||||
|
speed = (float)yawSpeed * delta * multiplier;
|
||||||
move = ideal - current;
|
move = ideal - current;
|
||||||
|
|
||||||
if (ideal > current)
|
if (ideal > current)
|
||||||
|
|||||||
@@ -138,40 +138,70 @@ void CMStukabat :: Precache()
|
|||||||
// AI Schedules Specific to this monster
|
// AI Schedules Specific to this monster
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
/* Chase */
|
// Chase enemy
|
||||||
Task_t tlStukabatChaseEnemy[] =
|
Task_t tlStukabatChaseEnemy[] =
|
||||||
{
|
{
|
||||||
{ TASK_GET_PATH_TO_ENEMY, (float)128 }, // is the 128 number really used?
|
{ TASK_SET_FAIL_SCHEDULE, (float)SCHED_CHASE_ENEMY_FAILED },
|
||||||
{ TASK_SET_ACTIVITY, (float)ACT_FLY },
|
{ TASK_GET_PATH_TO_ENEMY, (float)0 },
|
||||||
|
{ TASK_WALK_PATH, (float)0 }, // flying monster, use walk
|
||||||
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Schedule_t slStukabatChaseEnemy[] =
|
Schedule_t slStukabatChaseEnemy[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
tlStukabatChaseEnemy,
|
tlStukabatChaseEnemy,
|
||||||
ARRAYSIZE ( tlStukabatChaseEnemy ),
|
ARRAYSIZE ( tlStukabatChaseEnemy ),
|
||||||
bits_COND_NEW_ENEMY |
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_CAN_RANGE_ATTACK1 |
|
||||||
bits_COND_TASK_FAILED,
|
bits_COND_TASK_FAILED,
|
||||||
0,
|
0,
|
||||||
"Stukabat Chase Enemy"
|
"Stukabat Chase Enemy"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fail */
|
|
||||||
|
// Chase failed
|
||||||
|
Task_t tlStukabatChaseEnemyFailed[] =
|
||||||
|
{
|
||||||
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
|
{ TASK_WAIT, (float)0.2 },
|
||||||
|
{ TASK_FIND_COVER_FROM_ENEMY, (float)0 },
|
||||||
|
{ TASK_WALK_PATH, (float)0 },
|
||||||
|
{ TASK_WAIT_FOR_MOVEMENT, (float)0 },
|
||||||
|
{ TASK_REMEMBER, (float)bits_MEMORY_INCOVER },
|
||||||
|
// { TASK_TURN_LEFT, (float)179 },
|
||||||
|
{ TASK_FACE_ENEMY, (float)0 },
|
||||||
|
{ TASK_WAIT, (float)1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule_t slStukabatChaseEnemyFailed[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
tlStukabatChaseEnemyFailed,
|
||||||
|
ARRAYSIZE ( tlStukabatChaseEnemyFailed ),
|
||||||
|
bits_COND_NEW_ENEMY |
|
||||||
|
bits_COND_CAN_RANGE_ATTACK1,
|
||||||
|
0,
|
||||||
|
"Stukabat Chase Failed"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fail
|
||||||
Task_t tlStukabatFail[] =
|
Task_t tlStukabatFail[] =
|
||||||
{
|
{
|
||||||
{ TASK_STOP_MOVING, 0 },
|
{ TASK_STOP_MOVING, (float)0 },
|
||||||
{ TASK_SET_ACTIVITY, (float)ACT_HOVER },
|
{ TASK_SET_ACTIVITY, (float)ACT_HOVER },
|
||||||
{ TASK_WAIT, (float)2 },
|
{ TASK_WAIT, (float)2 },
|
||||||
{ TASK_WAIT_PVS, (float)0 },
|
{ TASK_WAIT_PVS, (float)0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
Schedule_t slStukabatFail[] =
|
Schedule_t slStukabatFail[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
tlStukabatFail,
|
tlStukabatFail,
|
||||||
ARRAYSIZE ( tlStukabatFail ),
|
ARRAYSIZE ( tlStukabatFail ),
|
||||||
0,
|
bits_COND_CAN_ATTACK,
|
||||||
0,
|
0,
|
||||||
"Stukabat Fail"
|
"Stukabat Fail"
|
||||||
},
|
},
|
||||||
@@ -181,6 +211,7 @@ Schedule_t slStukabatFail[] =
|
|||||||
DEFINE_CUSTOM_SCHEDULES( CMStukabat )
|
DEFINE_CUSTOM_SCHEDULES( CMStukabat )
|
||||||
{
|
{
|
||||||
slStukabatChaseEnemy,
|
slStukabatChaseEnemy,
|
||||||
|
slStukabatChaseEnemyFailed,
|
||||||
slStukabatFail,
|
slStukabatFail,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,9 +229,8 @@ void CMStukabat :: SetActivity ( Activity NewActivity )
|
|||||||
{
|
{
|
||||||
case ACT_IDLE:
|
case ACT_IDLE:
|
||||||
return; // refuse
|
return; // refuse
|
||||||
|
case ACT_HOVER:
|
||||||
case ACT_FLY:
|
case ACT_FLY:
|
||||||
iSequence = LookupActivity ( NewActivity );
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
iSequence = LookupActivity ( NewActivity );
|
iSequence = LookupActivity ( NewActivity );
|
||||||
break;
|
break;
|
||||||
@@ -238,6 +268,8 @@ Schedule_t* CMStukabat :: GetScheduleOfType ( int Type )
|
|||||||
{
|
{
|
||||||
case SCHED_CHASE_ENEMY:
|
case SCHED_CHASE_ENEMY:
|
||||||
return slStukabatChaseEnemy;
|
return slStukabatChaseEnemy;
|
||||||
|
case SCHED_CHASE_ENEMY_FAILED:
|
||||||
|
return slStukabatChaseEnemyFailed;
|
||||||
case SCHED_FAIL:
|
case SCHED_FAIL:
|
||||||
return slStukabatFail;
|
return slStukabatFail;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user