From 5f7abc2df06a7219598e6c592f36f1e2434ecad5 Mon Sep 17 00:00:00 2001 From: Giegue Date: Tue, 7 Feb 2023 18:19:52 -0300 Subject: [PATCH] Add monster_stukabat. --- src/dlls/cmflyingmonster.h | 28 ++++ src/dlls/dllapi.cpp | 4 + src/dlls/flyingmonster.cpp | 5 +- src/dlls/skill.cpp | 8 ++ src/dlls/skill.h | 7 +- src/dlls/stukabat.cpp | 259 +++++++++++++++++++++++++++++++++++++ 6 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 src/dlls/stukabat.cpp diff --git a/src/dlls/cmflyingmonster.h b/src/dlls/cmflyingmonster.h index 435474f..82a01e9 100644 --- a/src/dlls/cmflyingmonster.h +++ b/src/dlls/cmflyingmonster.h @@ -17,6 +17,8 @@ #ifndef FLYINGMONSTER_H #define FLYINGMONSTER_H +#include "cmbasemonster.h" + class CMFlyingMonster : public CMBaseMonster { public: @@ -49,5 +51,31 @@ protected: }; +//========================================================= +// Stukabat +//========================================================= +class CMStukabat : public CMFlyingMonster +{ +public: + void Spawn( void ); + void Precache( void ); + void SetYawSpeed( void ); + int Classify ( void ); + + void SetActivity ( Activity NewActivity ); + void HandleAnimEvent( MonsterEvent_t *pEvent ); + Schedule_t *GetScheduleOfType ( int Type ); + + int GetBitePitch( void ) { return PITCH_NORM + RANDOM_LONG( 40, 50 ); } + BOOL CheckRangeAttack1 ( float flDot, float flDist ); + + // Not used + BOOL CheckRangeAttack2 ( float flDot, float flDist ) { return FALSE; } + BOOL CheckMeleeAttack1 ( float flDot, float flDist ) { return FALSE; } + BOOL CheckMeleeAttack2 ( float flDot, float flDist ) { return FALSE; } + + CUSTOM_SCHEDULES +}; + #endif //FLYINGMONSTER_H diff --git a/src/dlls/dllapi.cpp b/src/dlls/dllapi.cpp index e8d9161..4bfb70c 100644 --- a/src/dlls/dllapi.cpp +++ b/src/dlls/dllapi.cpp @@ -163,6 +163,7 @@ monster_type_t monster_types[]= "monster_babygarg", FALSE, // Sven Co-op Monsters "monster_hwgrunt", FALSE, "monster_robogrunt", FALSE, + "monster_stukabat", FALSE, "info_node", FALSE, // Nodes "info_node_air", FALSE, "", FALSE @@ -634,6 +635,7 @@ bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_i case 26: monsters[monster_index].pMonster = CreateClassPtr((CMBabyGargantua *)NULL); break; case 27: monsters[monster_index].pMonster = CreateClassPtr((CMHWGrunt *)NULL); break; case 28: monsters[monster_index].pMonster = CreateClassPtr((CMRGrunt *)NULL); break; + case 29: monsters[monster_index].pMonster = CreateClassPtr((CMStukabat *)NULL); break; } if (monsters[monster_index].pMonster == NULL) @@ -1322,6 +1324,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) CMBabyGargantua babygargantua; CMHWGrunt hwgrunt; CMRGrunt rgrunt; + CMStukabat stukabat; g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" ); @@ -1368,6 +1371,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) case 26: babygargantua.Precache(); break; case 27: hwgrunt.Precache(); break; case 28: rgrunt.Precache(); break; + case 29: stukabat.Precache(); break; } } } diff --git a/src/dlls/flyingmonster.cpp b/src/dlls/flyingmonster.cpp index 41fa969..0bf3a95 100644 --- a/src/dlls/flyingmonster.cpp +++ b/src/dlls/flyingmonster.cpp @@ -16,15 +16,14 @@ #include "util.h" #include "cmbase.h" #include "cmbasemonster.h" +#include "cmflyingmonster.h" #include "monsters.h" -#include "schedule.h" +#include "schedule.h" #define FLYING_AE_FLAP (8) #define FLYING_AE_FLAPSOUND (9) -extern DLL_GLOBAL edict_t *g_pBodyQueueHead; - int CMFlyingMonster :: CheckLocalMove ( const Vector &vecStart, const Vector &vecEnd, edict_t *pTarget, float *pflDist ) { // UNDONE: need to check more than the endpoint diff --git a/src/dlls/skill.cpp b/src/dlls/skill.cpp index f0ae765..5c553b8 100644 --- a/src/dlls/skill.cpp +++ b/src/dlls/skill.cpp @@ -101,6 +101,9 @@ skill_cfg_t skill_cfg[] = { {"sk_hwgrunt_health", &gSkillData.hwgruntHealth}, {"sk_rgrunt_health", &gSkillData.rgruntHealth}, {"sk_rgrunt_armor", &gSkillData.rgruntArmor}, + {"sk_stukabat_health", &gSkillData.stukabatHealth}, + {"sk_stukabat_dmg_bite", &gSkillData.stukabatDmgBite}, + {"sk_stukabat_speed", &gSkillData.stukabatSpeed}, {"sk_12mm_bullet", &gSkillData.monDmg9MM}, {"sk_9mmAR_bullet", &gSkillData.monDmgMP5}, {"sk_9mm_bullet", &gSkillData.monDmg12MM}, @@ -295,6 +298,11 @@ void monster_skill_init(void) // Robo Grunt gSkillData.rgruntHealth = 50.0f; gSkillData.rgruntArmor = 0.75f; + + // Stukabat + gSkillData.stukabatHealth = 80.0f; + gSkillData.stukabatDmgBite = 12.0f; + gSkillData.stukabatSpeed = 400.0f; // MONSTER WEAPONS gSkillData.monDmg9MM = 5.0f; diff --git a/src/dlls/skill.h b/src/dlls/skill.h index 6eae1e3..1d1079c 100644 --- a/src/dlls/skill.h +++ b/src/dlls/skill.h @@ -126,10 +126,13 @@ struct skilldata_t float babygargDmgStomp; float hwgruntHealth; - + float rgruntHealth; float rgruntArmor; - + + float stukabatHealth; + float stukabatDmgBite; + float stukabatSpeed; // weapons shared by monsters float monDmg9MM; diff --git a/src/dlls/stukabat.cpp b/src/dlls/stukabat.cpp new file mode 100644 index 0000000..0dc7635 --- /dev/null +++ b/src/dlls/stukabat.cpp @@ -0,0 +1,259 @@ +/*** +* +* Copyright (c) 1996-2001, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* This source code contains proprietary and confidential information of +* Valve LLC and its suppliers. Access to this code is restricted to +* persons who have executed a written SDK license with Valve. Any access, +* use or distribution of this code by or to any unlicensed person is illegal. +* +****/ +//========================================================= +// Stukabat - Xen Birb +//========================================================= + +#include "extdll.h" +#include "util.h" +#include "cmbase.h" +#include "cmflyingmonster.h" +#include "monsters.h" +#include "schedule.h" +#include "animation.h" + +//========================================================= +// Monster's Anim Events Go Here +//========================================================= + +#define STUKABAT_AE_BITE 1 +#define STUKABAT_AE_FLAP 8 + +//========================================================= +// Classify - indicates this monster's place in the +// relationship table. +//========================================================= +int CMStukabat :: Classify ( void ) +{ + if ( m_iClassifyOverride == -1 ) // helper + return CLASS_NONE; + else if ( m_iClassifyOverride > 0 ) + return m_iClassifyOverride; // override + + return CLASS_ALIEN_PREDATOR; +} + +//========================================================= +// SetYawSpeed - allows each sequence to have a different +// turn rate associated with it. +//========================================================= +void CMStukabat :: SetYawSpeed ( void ) +{ + int ys; + + switch ( m_Activity ) + { + case ACT_HOVER: + default: + ys = 90; + } + + pev->yaw_speed = ys; +} + +//========================================================= +// HandleAnimEvent - catches the monster-specific messages +// that occur when tagged animation frames are played. +//========================================================= +void CMStukabat :: HandleAnimEvent( MonsterEvent_t *pEvent ) +{ + switch( pEvent->event ) + { + case STUKABAT_AE_BITE: + { + edict_t *pHurt = CheckTraceHullAttack( 70, gSkillData.stukabatDmgBite, DMG_SLASH|DMG_POISON ); + if ( pHurt ) + { + // Play bite sound + EMIT_SOUND_DYN( ENT(pev), CHAN_WEAPON, "headcrab/hc_headbite.wav", 1.0, ATTN_NORM, 0, GetBitePitch() ); + } + } + break; + case STUKABAT_AE_FLAP: + { + m_flightSpeed = gSkillData.stukabatSpeed; // set our own speed + } + break; + default: + CMFlyingMonster::HandleAnimEvent( pEvent ); + break; + } +} + +//========================================================= +// Spawn +//========================================================= +void CMStukabat :: Spawn() +{ + Precache( ); + + SET_MODEL(ENT(pev), "models/stukabat.mdl"); + UTIL_SetSize( pev, Vector( -12, -12, 0 ), Vector( 12, 12, 24 ) ); + + pev->solid = SOLID_SLIDEBOX; + pev->movetype = MOVETYPE_FLY; + pev->flags |= FL_FLY; + m_bloodColor = BLOOD_COLOR_YELLOW; + pev->health = gSkillData.stukabatHealth; + pev->view_ofs = Vector ( 0, 0, 22 );// position of the eyes relative to monster's origin. + m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) + m_MonsterState = MONSTERSTATE_NONE; + + m_pFlapSound = "stukabat/stukabat_flap1.wav"; + + MonsterInit(); + + pev->classname = MAKE_STRING( "monster_stukabat" ); + if ( strlen( STRING( m_szMonsterName ) ) == 0 ) + { + // default name + m_szMonsterName = MAKE_STRING( "Stukabat" ); + } +} + +//========================================================= +// Precache - precaches all resources this monster needs +//========================================================= +void CMStukabat :: Precache() +{ + PRECACHE_MODEL("models/stukabat.mdl"); + + PRECACHE_SOUND("stukabat/stukabat_flap1.wav"); // flying sound + PRECACHE_SOUND("headcrab/hc_headbite.wav"); // bite sound +} + +//========================================================= +// AI Schedules Specific to this monster +//========================================================= + +/* Chase */ +Task_t tlStukabatChaseEnemy[] = +{ + { TASK_GET_PATH_TO_ENEMY, (float)128 }, // is the 128 number really used? + { TASK_SET_ACTIVITY, (float)ACT_FLY }, + { TASK_WAIT_FOR_MOVEMENT, (float)0 }, + +}; +Schedule_t slStukabatChaseEnemy[] = +{ + { + tlStukabatChaseEnemy, + ARRAYSIZE ( tlStukabatChaseEnemy ), + bits_COND_NEW_ENEMY | + bits_COND_TASK_FAILED, + 0, + "StukabatChaseEnemy" + }, +}; + +/* Fail */ +Task_t tlStukabatFail[] = +{ + { TASK_STOP_MOVING, 0 }, + { TASK_SET_ACTIVITY, (float)ACT_HOVER }, + { TASK_WAIT, (float)2 }, + { TASK_WAIT_PVS, (float)0 }, +}; +Schedule_t slStukabatFail[] = +{ + { + tlStukabatFail, + ARRAYSIZE ( tlStukabatFail ), + 0, + 0, + "StukabatFail" + }, +}; + + +DEFINE_CUSTOM_SCHEDULES( CMStukabat ) +{ + slStukabatChaseEnemy, + slStukabatFail, +}; + +IMPLEMENT_CUSTOM_SCHEDULES( CMStukabat, CMFlyingMonster ); + +//========================================================= +// SetActivity +//========================================================= +void CMStukabat :: SetActivity ( Activity NewActivity ) +{ + int iSequence = ACTIVITY_NOT_AVAILABLE; + void *pmodel = GET_MODEL_PTR( ENT(pev) ); + + switch ( NewActivity ) + { + case ACT_IDLE: + return; // refuse + case ACT_FLY: + iSequence = LookupActivity ( NewActivity ); + break; + default: + iSequence = LookupActivity ( NewActivity ); + break; + } + + 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 + if ( iSequence > ACTIVITY_NOT_AVAILABLE ) + { + if ( pev->sequence != iSequence || !m_fSequenceLoops ) + { + pev->frame = 0; + } + + pev->sequence = iSequence; // Set to the reset anim (if it's there) + ResetSequenceInfo( ); + SetYawSpeed(); + } + else + { + // Not available try to get default anim + ALERT ( at_console, "%s has no sequence for act:%d\n", STRING(pev->classname), NewActivity ); + pev->sequence = 0; // Set to the reset anim (if it's there) + } +} + + +//========================================================= +// GetScheduleOfType +//========================================================= +Schedule_t* CMStukabat :: GetScheduleOfType ( int Type ) +{ + switch ( Type ) + { + case SCHED_CHASE_ENEMY: + return slStukabatChaseEnemy; + case SCHED_FAIL: + return slStukabatFail; + } + + return CMBaseMonster :: GetScheduleOfType( Type ); +} + + +//========================================================= +// CheckRangeAttack1 - Poisonous Bite +//========================================================= +BOOL CMStukabat :: CheckRangeAttack1 ( float flDot, float flDist ) +{ + if ( flDot > 0.7 && flDist <= 64 ) + { + return TRUE; + } + return FALSE; +}