Serious-Engine/Sources/Entities/Mamut.es
2016-04-08 00:11:36 +02:00

453 lines
15 KiB
C++

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)<m_fCloseDistance && CanHitEnemy(m_penEnemy, Cos(AngleDeg(130.0f)))) {
// set next shoot time
m_fShootTime = _pTimer->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();
};
};