327 %{ #include "Entities/StdH/StdH.h" #include "Models/Enemies/Mamut/MAMUT.H" #include "Models/Enemies/MAMUTMAN/Mamutman.h" %} uses "Entities/EnemyBase"; uses "Entities/Mamutman"; uses "Entities/AirWave"; uses "Entities/Bullet"; enum MamutChar { 0 MAT_SUMMER "Summer", 1 MAT_WINTER "Winter", }; %{ // info structure static EntityInfo eiMamut = { EIBT_FLESH, 2500.0f, 0.0f, 1.5f, 0.0f, 0.0f, 2.0f, 0.0f, }; #define HIT_DISTANCE 13.0f #define FIRE_BULLET FLOAT3D(0.0f*2, 4.0f*2, -4.0f*2) #define FIRE_AIRWAVE FLOAT3D(0.0f*2, 0.5f*2, -4.0f*2) #define RIDER_FRONT FLOAT3D( 0.25f*2, 6.5f*2, 0.5f*2) #define RIDER_MIDDLE FLOAT3D(-0.25f*2, 5.6f*2, 1.5f*2) #define RIDER_REAR FLOAT3D( 0.1f*2, 4.6f*2, 2.4f*2) %} class CMamut : CEnemyBase { name "Mamut"; thumbnail "Thumbnails\\Mamut.tbn"; properties: 1 enum MamutChar m_EmcChar "Character" 'C' = MAT_SUMMER, // character 2 BOOL m_bFrontRider "Rider Front" 'H' = FALSE, // front rider 3 BOOL m_bMiddleRider "Rider Middle" 'J' = FALSE, // middle rider 4 BOOL m_bRearRider "Rider Rear" 'K' = FALSE, // rear rider 5 CEntityPointer m_penBullet, // bullet 6 FLOAT m_fLastShootTime = 0.0f, components: 0 class CLASS_BASE "Classes\\EnemyBase.ecl", 1 class CLASS_BULLET "Classes\\Bullet.ecl", 2 class CLASS_MAMUTMAN "Classes\\Mamutman.ecl", 3 class CLASS_AIRWAVE "Classes\\AirWave.ecl", 10 model MODEL_MAMUT "Models\\Enemies\\Mamut\\Mamut.mdl", 11 texture TEXTURE_MAMUT_SUMMER "Models\\Enemies\\Mamut\\Mamut.tex", 12 texture TEXTURE_MAMUT_WINTER "Models\\Enemies\\Mamut\\Mamut3.tex", 20 model MODEL_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.mdl", 21 texture TEXTURE_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.tex", // ************** SOUNDS ************** 50 sound SOUND_IDLE "Models\\Enemies\\Mamut\\Sounds\\Idle.wav", 51 sound SOUND_SIGHT "Models\\Enemies\\Mamut\\Sounds\\Sight.wav", 52 sound SOUND_WOUND "Models\\Enemies\\Mamut\\Sounds\\Wound.wav", 53 sound SOUND_FIRE "Models\\Enemies\\Mamut\\Sounds\\Fire.wav", 54 sound SOUND_KICK "Models\\Enemies\\Mamut\\Sounds\\Kick.wav", 55 sound SOUND_DEATH "Models\\Enemies\\Mamut\\Sounds\\Death.wav", functions: /* Entity info */ void *GetEntityInfo(void) { return &eiMamut; }; /* Receive damage */ void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) { // mamut can't harm mamut if (!IsOfClass(penInflictor, "Mamut")) { CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); } }; // play attachmnet anim void PlayAttachmentAnim(INDEX iAttachment, INDEX iAnim, ULONG ulFlags) { CAttachmentModelObject *amo = GetModelObject()->GetAttachmentModel(iAttachment); if (amo!=NULL) { amo->amo_moModelObject.PlayAnim(iAnim, ulFlags); } }; // death INDEX AnimForDeath(void) { StartModelAnim(MAMUT_ANIM_DEATH, 0); return MAMUT_ANIM_DEATH; }; void DeathNotify(void) { ChangeCollisionBoxIndexWhenPossible(MAMUT_COLLISION_BOX_DEATH); DropRiders(TRUE); }; // drop riders void CreateRider(const FLOAT3D &vPos, INDEX iRider) { // mamutman start position CPlacement3D pl; pl.pl_OrientationAngle = ANGLE3D(0,0,0); pl.pl_PositionVector = vPos; pl.RelativeToAbsolute(GetPlacement()); // create rider CEntityPointer pen = CreateEntity(pl, CLASS_MAMUTMAN); ((CMamutman&)*pen).m_bSpawned = TRUE; ((CMamutman&)*pen).m_bSpawnedPosition = iRider; ((CMamutman&)*pen).m_penEnemy = m_penEnemy; ((CMamutman&)*pen).m_ttTarget = m_ttTarget; pen->Initialize(EVoid()); }; void DropRiders(BOOL bAlways) { if (m_bFrontRider && (bAlways || (IRnd()&1))) { m_bFrontRider = FALSE; CreateRider(RIDER_FRONT, 0); RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT); } if (m_bMiddleRider && (bAlways || (IRnd()&1))) { m_bMiddleRider = FALSE; CreateRider(RIDER_MIDDLE, 1); RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE); } if (m_bRearRider && (bAlways || (IRnd()&1))) { m_bRearRider = FALSE; CreateRider(RIDER_REAR, 2); RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR); } }; // virtual anim functions void StandingAnim(void) { StartModelAnim(MAMUT_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_STANDMOUNTEDFIRST, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_STANDMOUNTEDSECOND, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_STANDMOUNTEDTHIRD, 0); }; void WalkingAnim(void) { StartModelAnim(MAMUT_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDWALKFIRST, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDWALKSECOND, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDWALKTHIRD, 0); }; void RunningAnim(void) { StartModelAnim(MAMUT_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDRUNFIRST, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDRUNSECOND, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDRUNTHIRD, 0); }; void RotatingAnim(void) { StartModelAnim(MAMUT_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDWALKFIRST, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDWALKSECOND, 0); PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDWALKTHIRD, 0); }; // virtual sound functions void IdleSound(void) { PlaySound(m_soSound, SOUND_IDLE, SOF_3D); }; void SightSound(void) { PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); }; void WoundSound(void) { PlaySound(m_soSound, SOUND_WOUND, SOF_3D); }; void DeathSound(void) { PlaySound(m_soSound, SOUND_DEATH, SOF_3D); }; /************************************************************ * FIRE BULLET * ************************************************************/ // prepare bullet void PrepareBullet(void) { // bullet start position CPlacement3D plBullet; plBullet.pl_OrientationAngle = ANGLE3D(0,0,0); plBullet.pl_PositionVector = FIRE_BULLET; plBullet.RelativeToAbsolute(GetPlacement()); // create bullet m_penBullet = CreateEntity(plBullet, CLASS_BULLET); // init bullet EBulletInit eInit; eInit.penOwner = this; eInit.fDamage = 1.0f; m_penBullet->Initialize(eInit); ((CBullet&)*m_penBullet).CalcTarget(m_penEnemy, 100); }; // fire bullet void FireBullet(void) { ((CBullet&)*m_penBullet).LaunchBullet(TRUE, TRUE, TRUE); ((CBullet&)*m_penBullet).DestroyBullet(); }; // fire air wave void FireAirWave(void) { // target enemy body EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); FLOAT3D vShootTarget; GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); // launch CPlacement3D pl; PrepareFreeFlyingProjectile(pl, vShootTarget, FIRE_AIRWAVE, ANGLE3D(0, 0, 0)); CEntityPointer penProjectile = CreateEntity(pl, CLASS_AIRWAVE); EAirWave eLaunch; eLaunch.penLauncher = this; penProjectile->Initialize(eLaunch); }; procedures: /************************************************************ * PROCEDURES WHEN HARMED * ************************************************************/ // Play wound animation and falling body part BeWounded(EDamage eDamage) : CEnemyBase::BeWounded { StopMoving(); // damage anim StartModelAnim(MAMUT_ANIM_WOUND02, 0); autowait(0.5f); // drop riders if (GetHealth()<600.0f) { DropRiders(GetHealth()<250.0f); } autowait(1.5f); return EReturn(); }; /************************************************************ * A T T A C K E N E M Y * ************************************************************/ /* // initial preparation InitializeAttack(EVoid) : CEnemyBase::InitializeAttack { m_fLastShootTime = 0.0f; jump CEnemyBase::InitializeAttack(); }; // attack shoot AttackShoot() : CEnemyBase::AttackShoot { // shoot at enemy if possible if (CanAttackEnemy(m_penEnemy, Cos(AngleDeg(130.0f)))) { // set next shoot time m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/3.0f); // fire // mamut shoot if (m_fLastShootTime+4.0f<_pTimer->CurrentTick() && CanAttackEnemy(m_penEnemy, Cos(AngleDeg(50.0f)))) { // stop moving (rotation and translation) StopMoving(); autocall Fire() EReturn; // rider (mamutman) shoot } else if (m_bFrontRider || m_bMiddleRider || m_bRearRider) { // stop rotating StopRotating(); autocall RiderFire() EReturn; } } else { // safety precocious from stack overflow loop m_fShootTime = _pTimer->CurrentTick() + 0.25f; } return ETimer(); }; // close shoot CloseShoot() : CEnemyBase::CloseShoot { // shoot at enemy if possible if (CalcDist(m_penEnemy)CurrentTick() + m_fCloseFireTime*(1.0f + FRnd()/3.0f); // hit // mamut shoot if (m_fLastShootTime+4.0f<_pTimer->CurrentTick() && CanHitEnemy(m_penEnemy, Cos(AngleDeg(50.0f)))) { // stop moving (rotaion and translation) StopMoving(); autocall Hit() EReturn; // rider (mamutman) shoot } else if (m_bFrontRider || m_bMiddleRider || m_bRearRider) { // stop rotating StopRotating(); autocall RiderFire() EReturn; } // try attack shoot } else { jump AttackShoot(); } return ETimer(); }; */ Fire(EVoid) : CEnemyBase::Fire { m_fLastShootTime = _pTimer->CurrentTick(); // fire projectile StartModelAnim(MAMUT_ANIM_WOUND01, 0); autowait(1.1f); FireAirWave(); PlaySound(m_soSound, SOUND_FIRE, SOF_3D); autowait(FRnd()*0.2f); return EReturn(); }; Hit(EVoid) : CEnemyBase::Hit { m_fLastShootTime = _pTimer->CurrentTick(); // hit the ground StartModelAnim(MAMUT_ANIM_ATTACK01, 0); autowait(0.3f); if (CalcDist(m_penEnemy) < HIT_DISTANCE) { FLOAT3D vSource = GetPlacement().pl_PositionVector + FLOAT3D(en_mRotation(1, 2), en_mRotation(2, 2), en_mRotation(3, 2)); PlaySound(m_soSound, SOUND_KICK, SOF_3D); // damage InflictRangeDamage(this, DMT_CLOSERANGE, 20.0f, vSource, 1.0f, 15.0f); } autowait(0.5f); if (CalcDist(m_penEnemy) < HIT_DISTANCE) { FLOAT3D vSource = GetPlacement().pl_PositionVector + FLOAT3D(en_mRotation(1, 2), en_mRotation(2, 2), en_mRotation(3, 2)); PlaySound(m_soSound, SOUND_KICK, SOF_3D); // damage InflictRangeDamage(this, DMT_CLOSERANGE, 20.0f, vSource, 1.0f, 15.0f); } autowait(0.7f+FRnd()*0.1f); return EReturn(); }; RiderFire() { // if have any rider fire if (m_bFrontRider || m_bMiddleRider || m_bRearRider) { // prepare PrepareBullet(); // find valid rider INDEX iRider = IRnd()%3; if (iRider==0 && !m_bFrontRider) { iRider = 1; } if (iRider==1 && !m_bMiddleRider) { iRider = 2; } if (iRider==2 && !m_bRearRider) { iRider = 0; } if (iRider==0 && !m_bFrontRider) { iRider = 1; } if (iRider==1 && !m_bMiddleRider) { iRider = 2; } // animation switch (iRider) { case 0: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDATTACKFIRST, 0); break; case 1: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDATTACKSECOND, 0); break; case 2: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDATTACKTHIRD, 0); break; } // fire bullet autowait(0.8f); PlaySound(m_soSound, SOUND_FIRE, SOF_3D); FireBullet(); } return EReturn(); }; /************************************************************ * M A I N * ************************************************************/ Main(EVoid) { // declare yourself as a model InitAsModel(); SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); SetCollisionFlags(ECF_MODEL); SetFlags(GetFlags()|ENF_ALIVE); en_tmMaxHoldBreath = 35.0f; en_fDensity = 4000.0f; // set your appearance GetModelObject()->StretchModel(FLOAT3D(2,2,2)); SetModel(MODEL_MAMUT); ModelChangeNotify(); if (m_EmcChar==MAT_SUMMER) { SetModelMainTexture(TEXTURE_MAMUT_SUMMER); } else { SetModelMainTexture(TEXTURE_MAMUT_WINTER); } SetHealth(700.0f); m_fMaxHealth = 700.0f; // set riders RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT); RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE); RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR); if (m_bFrontRider) { AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT, MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0); } if (m_bMiddleRider) { AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE, MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0); } if (m_bRearRider) { AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR, MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0); } StandingAnim(); // setup moving speed m_fWalkSpeed = FRnd() + 1.0f; m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f); m_fAttackRunSpeed = FRnd() + 9.0f; m_aAttackRotateSpeed = AngleDeg(FRnd()*15.0f + 250.0f); m_fCloseRunSpeed = FRnd() + 10.0f; m_aCloseRotateSpeed = AngleDeg(FRnd()*15.0f + 250.0f); // setup attack distances m_fAttackDistance = 120.0f; m_fCloseDistance = 14.0f; m_fStopDistance = 12.0f; INDEX iTime = 4.0f; if (m_bFrontRider) { iTime--; } if (m_bMiddleRider) { iTime--; } if (m_bRearRider) { iTime--; } m_fAttackFireTime = iTime; m_fCloseFireTime = 0.5f; m_fIgnoreRange = 200.0f; // damage/explode properties m_fBlowUpAmount = 250.0f; m_fBodyParts = 5; m_fDamageWounded = 200.0f; m_iScore = 5000; // continue behavior in base class jump CEnemyBase::MainLoop(); }; };