2016-03-12 01:20:51 +01:00
|
|
|
/* Copyright (c) 2002-2012 Croteam Ltd.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation
|
|
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
|
2016-03-11 14:57:17 +01:00
|
|
|
|
|
|
|
321
|
|
|
|
%{
|
2016-04-01 20:04:24 +02:00
|
|
|
#include "EntitiesMP/StdH/StdH.h"
|
2016-03-29 03:03:54 +02:00
|
|
|
#include "Models/Enemies/DragonMan/DragonMan.h"
|
2016-03-11 14:57:17 +01:00
|
|
|
%}
|
|
|
|
|
|
|
|
uses "EntitiesMP/EnemyFly";
|
|
|
|
uses "EntitiesMP/Projectile";
|
|
|
|
|
|
|
|
enum DragonmanType {
|
|
|
|
0 DT_SOLDIER "Soldier",
|
|
|
|
1 DT_SERGEANT "Sergeant",
|
|
|
|
2 DT_MONSTER "Monster",
|
|
|
|
};
|
|
|
|
|
|
|
|
%{
|
|
|
|
// info structure
|
|
|
|
static EntityInfo eiDragonmanStand1 = {
|
|
|
|
EIBT_FLESH, 200.0f,
|
|
|
|
0.0f, 1.55f, 0.0f,
|
|
|
|
0.0f, 1.0f, 0.0f,
|
|
|
|
};
|
|
|
|
static EntityInfo eiDragonmanStand2 = {
|
|
|
|
EIBT_FLESH, 200.0f*2,
|
|
|
|
0.0f, 1.55f*2, 0.0f,
|
|
|
|
0.0f, 1.0f*2, 0.0f,
|
|
|
|
};
|
|
|
|
static EntityInfo eiDragonmanStand4 = {
|
|
|
|
EIBT_FLESH, 200.0f*4,
|
|
|
|
0.0f, 1.55f*4, 0.0f,
|
|
|
|
0.0f, 1.0f*4, 0.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
static EntityInfo eiDragonmanFly1 = {
|
|
|
|
EIBT_FLESH, 100.0f*1,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
};
|
|
|
|
static EntityInfo eiDragonmanFly2 = {
|
|
|
|
EIBT_FLESH, 100.0f*2,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
};
|
|
|
|
static EntityInfo eiDragonmanFly4 = {
|
|
|
|
EIBT_FLESH, 100.0f*4,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
0.0f, 0.0f, 0.0f,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define FLY_FIRE1 FLOAT3D( 0.0f, 0.25f, -1.5f)
|
|
|
|
#define GROUND_RIGHT_FIRE1 FLOAT3D( 0.3f, 2.2f, -0.85f)
|
|
|
|
#define GROUND_LEFT_FIRE1 FLOAT3D(-0.3f, 1.7f, -0.85f)
|
|
|
|
#define FLAME_AIR1 FLOAT3D( 0.0f, 0.1f, -1.75f)
|
|
|
|
#define FLAME_GROUND1 FLOAT3D( 0.0f, 2.7f, -0.85f)
|
|
|
|
%}
|
|
|
|
|
|
|
|
|
|
|
|
class CDragonman : CEnemyFly {
|
|
|
|
name "Dragonman";
|
|
|
|
thumbnail "Thumbnails\\Dragonman.tbn";
|
|
|
|
|
|
|
|
properties:
|
|
|
|
1 enum DragonmanType m_EdtType "Character" 'C' = DT_SOLDIER, // type
|
|
|
|
2 FLOAT3D m_vFlameSource = FLOAT3D(0,0,0),
|
|
|
|
3 CEntityPointer m_penFlame,
|
|
|
|
4 BOOL m_bBurnEnemy = FALSE,
|
|
|
|
5 FLOAT m_fFireTime = 0.0f,
|
|
|
|
|
|
|
|
components:
|
|
|
|
0 class CLASS_BASE "Classes\\EnemyFly.ecl",
|
|
|
|
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
|
|
|
|
|
|
|
|
5 model MODEL_DRAGONMAN "Models\\Enemies\\Dragonman\\Dragonman.mdl",
|
|
|
|
6 texture TEXTURE_DRAGONMAN1 "Models\\Enemies\\Dragonman\\Dragonman01.tex",
|
|
|
|
7 texture TEXTURE_DRAGONMAN2 "Models\\Enemies\\Dragonman\\Dragonman02.tex",
|
|
|
|
8 texture TEXTURE_DRAGONMAN3 "Models\\Enemies\\Dragonman\\Dragonman03.tex",
|
|
|
|
|
|
|
|
// ************** SOUNDS **************
|
|
|
|
50 sound SOUND_IDLE "Models\\Enemies\\Dragonman\\Sounds\\Idle.wav",
|
|
|
|
51 sound SOUND_SIGHT "Models\\Enemies\\Dragonman\\Sounds\\Sight.wav",
|
|
|
|
52 sound SOUND_WOUND "Models\\Enemies\\Dragonman\\Sounds\\Wound.wav",
|
|
|
|
53 sound SOUND_FIRE "Models\\Enemies\\Dragonman\\Sounds\\Fire.wav",
|
|
|
|
54 sound SOUND_KICK "Models\\Enemies\\Dragonman\\Sounds\\Kick.wav",
|
|
|
|
55 sound SOUND_DEATH "Models\\Enemies\\Dragonman\\Sounds\\Death.wav",
|
|
|
|
|
|
|
|
functions:
|
|
|
|
/* Entity info */
|
|
|
|
void *GetEntityInfo(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
switch(m_EdtType) {
|
|
|
|
case DT_SOLDIER:
|
|
|
|
return &eiDragonmanFly1;
|
|
|
|
break;
|
|
|
|
case DT_SERGEANT:
|
|
|
|
return &eiDragonmanFly2;
|
|
|
|
break;
|
|
|
|
case DT_MONSTER:
|
|
|
|
return &eiDragonmanFly4;
|
|
|
|
break;
|
|
|
|
default: {
|
|
|
|
return &eiDragonmanFly1;
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch(m_EdtType) {
|
|
|
|
case DT_SOLDIER:
|
|
|
|
return &eiDragonmanStand1;
|
|
|
|
break;
|
|
|
|
case DT_SERGEANT:
|
|
|
|
return &eiDragonmanStand2;
|
|
|
|
break;
|
|
|
|
case DT_MONSTER:
|
|
|
|
return &eiDragonmanStand4;
|
|
|
|
break;
|
|
|
|
default: {
|
|
|
|
return &eiDragonmanStand1;
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Fill in entity statistics - for AI purposes only */
|
|
|
|
BOOL FillEntityStatistics(EntityStats *pes)
|
|
|
|
{
|
|
|
|
CEnemyBase::FillEntityStatistics(pes);
|
|
|
|
switch(m_EdtType) {
|
|
|
|
case DT_SOLDIER : { pes->es_strName+=" Soldier"; } break;
|
|
|
|
case DT_SERGEANT : { pes->es_strName+=" Sergeant"; } break;
|
|
|
|
case DT_MONSTER : { pes->es_strName+=" Monster"; } break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Receive damage */
|
|
|
|
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
|
|
|
|
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
|
|
|
|
{
|
|
|
|
// woman can't harm woman
|
|
|
|
if (!IsOfClass(penInflictor, "Dragonman")) {
|
|
|
|
CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
FLOAT3D GetStretchedVector(const FLOAT3D&v)
|
|
|
|
{
|
|
|
|
switch(m_EdtType) {
|
|
|
|
case DT_SOLDIER:
|
|
|
|
return v;
|
|
|
|
break;
|
|
|
|
case DT_SERGEANT:
|
|
|
|
return v*2.0f;
|
|
|
|
break;
|
|
|
|
case DT_MONSTER:
|
|
|
|
return v*4.0f;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ASSERT(FALSE);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// damage anim
|
|
|
|
INDEX AnimForDamage(FLOAT fDamage) {
|
|
|
|
INDEX iAnim;
|
|
|
|
if (m_bInAir) {
|
|
|
|
switch (IRnd()%2) {
|
|
|
|
case 0: iAnim = DRAGONMAN_ANIM_AIRWOUNDSLIGHT; break;
|
|
|
|
case 1: iAnim = DRAGONMAN_ANIM_AIRWOUND02CRITICAL; break;
|
|
|
|
default: ASSERTALWAYS("Dragonman unknown fly damage");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (IRnd()%3) {
|
|
|
|
case 0: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK; break;
|
|
|
|
case 1: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALFRONT; break;
|
|
|
|
case 2: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK2; break;
|
|
|
|
default: ASSERTALWAYS("Dragonman unknown ground damage");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StartModelAnim(iAnim, 0);
|
|
|
|
return iAnim;
|
|
|
|
};
|
|
|
|
|
|
|
|
// death
|
|
|
|
INDEX AnimForDeath(void) {
|
|
|
|
INDEX iAnim;
|
|
|
|
if (m_bInAir) {
|
|
|
|
iAnim = DRAGONMAN_ANIM_AIRDEATH;
|
|
|
|
} else {
|
|
|
|
switch (IRnd()%2) {
|
|
|
|
case 0: iAnim = DRAGONMAN_ANIM_GROUNDDEATHBACK; break;
|
|
|
|
case 1: iAnim = DRAGONMAN_ANIM_GROUNDDEATHFRONT; break;
|
|
|
|
default: ASSERTALWAYS("Dragonman unknown ground death");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StartModelAnim(iAnim, 0);
|
|
|
|
return iAnim;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DeathNotify(void) {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_DEATH);
|
|
|
|
en_fDensity = 500.0f;
|
|
|
|
};
|
|
|
|
|
|
|
|
// virtual anim functions
|
|
|
|
void StandingAnim(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRSTANDLOOP, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDSTANDLOOP, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void WalkingAnim(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void RunningAnim(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
void RotatingAnim(void) {
|
|
|
|
if (m_bInAir) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
} else {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
FLOAT AirToGroundAnim(void) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRTOGROUND, 0);
|
|
|
|
return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_AIRTOGROUND));
|
|
|
|
};
|
|
|
|
FLOAT GroundToAirAnim(void) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDTOAIR, 0);
|
|
|
|
return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_GROUNDTOAIR));
|
|
|
|
};
|
|
|
|
void ChangeCollisionToAir() {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_AIR);
|
|
|
|
};
|
|
|
|
void ChangeCollisionToGround() {
|
|
|
|
ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_GROUND);
|
|
|
|
};
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
};
|
|
|
|
|
|
|
|
// flame source
|
|
|
|
void GetFlamerSourcePlacement(CPlacement3D &plFlame) {
|
|
|
|
plFlame.pl_PositionVector = m_vFlameSource;
|
|
|
|
};
|
|
|
|
|
|
|
|
// fire flame
|
|
|
|
void FireFlame(void) {
|
|
|
|
FLOAT3D vFlamePos;
|
|
|
|
if (m_bInAir) {
|
|
|
|
vFlamePos = GetStretchedVector(FLAME_AIR1);
|
|
|
|
} else {
|
|
|
|
vFlamePos = GetStretchedVector(FLAME_GROUND1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// create flame
|
|
|
|
CEntityPointer penFlame = ShootProjectile(PRT_FLAME, vFlamePos, ANGLE3D(0, 0, 0));
|
|
|
|
// link last flame with this one (if not NULL or deleted)
|
|
|
|
if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
|
|
|
|
((CProjectile&)*m_penFlame).m_penParticles = penFlame;
|
|
|
|
}
|
|
|
|
// link to player weapons
|
|
|
|
((CProjectile&)*penFlame).m_penParticles = this;
|
|
|
|
// store last flame
|
|
|
|
m_penFlame = penFlame;
|
|
|
|
// flame source position
|
|
|
|
m_vFlameSource = GetPlacement().pl_PositionVector + vFlamePos*GetRotationMatrix();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
procedures:
|
|
|
|
/************************************************************
|
|
|
|
* PROCEDURES WHEN HARMED *
|
|
|
|
************************************************************/
|
|
|
|
BeWounded(EDamage eDamage) : CEnemyFly::BeWounded {
|
|
|
|
m_penFlame = NULL;
|
|
|
|
jump CEnemyFly::BeWounded(eDamage);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************
|
|
|
|
* A T T A C K E N E M Y *
|
|
|
|
************************************************************/
|
|
|
|
FlyFire(EVoid) : CEnemyFly::FlyFire {
|
|
|
|
// fire projectile
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0);
|
|
|
|
autowait(0.4f);
|
|
|
|
if (m_EdtType != DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
} else {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
}
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
|
|
autowait(0.15f);
|
|
|
|
if (m_EdtType != DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
} else if (m_EdtType == DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
}
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
|
|
autowait(0.85f);
|
|
|
|
/* StandingAnim();
|
|
|
|
autowait(FRnd() + _pTimer->TickQuantum);
|
|
|
|
*/
|
|
|
|
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
FlyHit(EVoid) : CEnemyFly::FlyHit {
|
|
|
|
// fly
|
|
|
|
if (CalcDist(m_penEnemy) <= 7.5f) {
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
jump FlyOnEnemy();
|
|
|
|
} else {
|
|
|
|
jump FlyBurn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// run to enemy
|
|
|
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
FlyOnEnemy(EVoid) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRATTACKCLOSELOOP, 0);
|
|
|
|
|
|
|
|
// jump
|
|
|
|
FLOAT3D vDir = PlayerDestinationPos();
|
|
|
|
vDir = (vDir - GetPlacement().pl_PositionVector).Normalize();
|
|
|
|
vDir *= !GetRotationMatrix();
|
|
|
|
vDir *= m_fFlyCloseRunSpeed*1.9f;
|
|
|
|
SetDesiredTranslation(vDir);
|
|
|
|
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
|
|
|
|
|
|
|
|
// animation - IGNORE DAMAGE WOUND -
|
|
|
|
SpawnReminder(this, 0.9f, 0);
|
|
|
|
m_iChargeHitAnimation = DRAGONMAN_ANIM_AIRATTACKCLOSELOOP;
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
m_fChargeHitDamage = 25.0f;
|
|
|
|
m_fChargeHitSpeed = 15.0f;
|
|
|
|
} else if (m_EdtType == DT_SERGEANT) {
|
|
|
|
m_fChargeHitDamage = 30.0f;
|
|
|
|
m_fChargeHitSpeed = 20.0f;
|
|
|
|
} else if (TRUE) {
|
|
|
|
m_fChargeHitDamage = 30.0f;
|
|
|
|
m_fChargeHitSpeed = 20.0f;
|
|
|
|
}
|
|
|
|
m_fChargeHitAngle = 0.0f;
|
|
|
|
autocall CEnemyBase::ChargeHitEnemy() EReturn;
|
|
|
|
|
|
|
|
StandingAnim();
|
|
|
|
autowait(0.3f);
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
FlyBurn(EVoid) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0);
|
|
|
|
|
|
|
|
// burn
|
|
|
|
m_fFireTime = _pTimer->CurrentTick();
|
|
|
|
FireFlame();
|
|
|
|
m_bBurnEnemy = TRUE;
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP);
|
|
|
|
while (m_bBurnEnemy) {
|
|
|
|
m_fMoveFrequency = 0.1f;
|
|
|
|
wait(m_fMoveFrequency) {
|
|
|
|
// flame
|
|
|
|
on (EBegin) : {
|
|
|
|
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
|
|
|
|
// rotate to enemy
|
|
|
|
m_aRotateSpeed = 10000.0f;
|
|
|
|
m_fMoveSpeed = 0.0f;
|
|
|
|
// flame
|
|
|
|
FireFlame();
|
|
|
|
// stop
|
|
|
|
if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) {
|
|
|
|
m_bBurnEnemy = FALSE;
|
|
|
|
stop;
|
|
|
|
}
|
|
|
|
// adjust direction and speed
|
|
|
|
ULONG ulFlags = SetDesiredMovement();
|
|
|
|
MovementAnimation(ulFlags);
|
|
|
|
resume;
|
|
|
|
}
|
|
|
|
on (ETimer) : { stop; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_soSound.Stop();
|
|
|
|
|
|
|
|
// link last flame with nothing (if not NULL or deleted)
|
|
|
|
if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
|
|
|
|
((CProjectile&)*m_penFlame).m_penParticles = NULL;
|
|
|
|
m_penFlame = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
StandingAnim();
|
|
|
|
autowait(0.3f);
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
Fire(EVoid) : CEnemyBase::Fire {
|
|
|
|
// fire projectile
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKCLOSELOOP, 0);
|
|
|
|
autowait(0.3f);
|
|
|
|
if (m_EdtType != DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
} else {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
}
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
|
|
autowait(0.8f);
|
|
|
|
if (m_EdtType != DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
} else if (m_EdtType == DT_MONSTER) {
|
|
|
|
ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0));
|
|
|
|
}
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
|
|
|
|
autowait(0.55f);
|
|
|
|
StandingAnim();
|
|
|
|
autowait(FRnd() + _pTimer->TickQuantum);
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
Hit(EVoid) : CEnemyBase::Hit {
|
|
|
|
// burn enemy
|
|
|
|
if (m_EdtType == DT_SERGEANT && CalcDist(m_penEnemy) <= 6.0f ||
|
|
|
|
m_EdtType == DT_MONSTER && CalcDist(m_penEnemy) <= 20.0f) {
|
|
|
|
jump BurnEnemy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// run to enemy
|
|
|
|
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
|
|
|
|
return EReturn();
|
|
|
|
};
|
|
|
|
|
|
|
|
BurnEnemy(EVoid) {
|
|
|
|
StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKDISTANT, 0);
|
|
|
|
|
|
|
|
// burn
|
|
|
|
m_fFireTime = _pTimer->CurrentTick();
|
|
|
|
FireFlame();
|
|
|
|
m_bBurnEnemy = TRUE;
|
|
|
|
PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP);
|
|
|
|
while (m_bBurnEnemy) {
|
|
|
|
m_fMoveFrequency = 0.1f;
|
|
|
|
wait(m_fMoveFrequency) {
|
|
|
|
// flame
|
|
|
|
on (EBegin) : {
|
|
|
|
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
|
|
|
|
// rotate to enemy
|
|
|
|
m_fMoveSpeed = 0.0f;
|
|
|
|
m_aRotateSpeed = 10000.0f;
|
|
|
|
// adjust direction and speed
|
|
|
|
SetDesiredMovement();
|
|
|
|
// flame
|
|
|
|
FireFlame();
|
|
|
|
// stop
|
|
|
|
if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) {
|
|
|
|
m_bBurnEnemy = FALSE;
|
|
|
|
stop;
|
|
|
|
}
|
|
|
|
resume;
|
|
|
|
}
|
|
|
|
on (ETimer) : { stop; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_soSound.Stop();
|
|
|
|
|
|
|
|
// link last flame with nothing (if not NULL or deleted)
|
|
|
|
if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) {
|
|
|
|
((CProjectile&)*m_penFlame).m_penParticles = NULL;
|
|
|
|
m_penFlame = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
StandingAnim();
|
|
|
|
autowait(0.3f);
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
|
|
|
|
ModelChangeNotify();
|
|
|
|
SetHealth(150.0f);
|
|
|
|
m_fMaxHealth = 150.0f;
|
|
|
|
m_fDamageWounded = 100.0f;
|
|
|
|
} else if (m_EdtType == DT_SERGEANT) {
|
|
|
|
GetModelObject()->StretchModel(FLOAT3D(2.0f, 2.0f, 2.0f));
|
|
|
|
ModelChangeNotify();
|
|
|
|
SetHealth(450.0f);
|
|
|
|
m_fMaxHealth = 450.0f;
|
|
|
|
m_fDamageWounded = 300.0f;
|
|
|
|
} else if (TRUE) {
|
|
|
|
GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f));
|
|
|
|
ModelChangeNotify();
|
|
|
|
SetHealth(1350.0f);
|
|
|
|
m_fMaxHealth = 1350.0f;
|
|
|
|
m_fDamageWounded = 1000.0f;
|
|
|
|
}
|
|
|
|
en_tmMaxHoldBreath = 10.0f;
|
|
|
|
en_fDensity = 2000.0f;
|
|
|
|
|
|
|
|
// set your appearance
|
|
|
|
SetModel(MODEL_DRAGONMAN);
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
SetModelMainTexture(TEXTURE_DRAGONMAN1);
|
|
|
|
} else if (m_EdtType == DT_SERGEANT) {
|
|
|
|
SetModelMainTexture(TEXTURE_DRAGONMAN2);
|
|
|
|
} else if (TRUE) {
|
|
|
|
SetModelMainTexture(TEXTURE_DRAGONMAN3);
|
|
|
|
}
|
|
|
|
// setup moving speed
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
m_fWalkSpeed = FRnd()*1.5f + 2.5f;
|
|
|
|
m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
|
|
|
|
m_fAttackRunSpeed = FRnd()*2.0f + 11.0f;
|
|
|
|
m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
|
|
|
|
m_fCloseRunSpeed = FRnd()*2.0f + 6.0f;
|
|
|
|
m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
|
|
|
|
} else if (m_EdtType == DT_SERGEANT) {
|
|
|
|
m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*1.5f;
|
|
|
|
m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
|
|
|
|
m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*2;
|
|
|
|
m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
|
|
|
|
m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*1.5f;
|
|
|
|
m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
|
|
|
|
} else if (TRUE) {
|
|
|
|
m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*2;
|
|
|
|
m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f;
|
|
|
|
m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*4;
|
|
|
|
m_aAttackRotateSpeed = FRnd()*75 + 350.0f;
|
|
|
|
m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*2;
|
|
|
|
m_aCloseRotateSpeed = FRnd()*50 + 500.0f;
|
|
|
|
}
|
|
|
|
// setup attack distances
|
|
|
|
m_fAttackDistance = 100.0f;
|
|
|
|
if (m_EdtType == DT_SOLDIER) {
|
|
|
|
m_fCloseDistance = 0.0f;
|
|
|
|
m_fStopDistance = 10.0f;
|
|
|
|
m_fFlyCloseDistance = 12.5f;
|
|
|
|
m_fFlyStopDistance = 0.0f;
|
|
|
|
m_iScore = 1000;
|
|
|
|
} else if (m_EdtType == DT_SERGEANT) {
|
|
|
|
m_fCloseDistance = 20.0f;
|
|
|
|
m_fStopDistance = 0.0f;
|
|
|
|
m_fFlyCloseDistance = 12.5f*2;
|
|
|
|
m_fFlyStopDistance = 0.0f;
|
|
|
|
m_iScore = 2000;
|
|
|
|
} else {
|
|
|
|
m_fCloseDistance = 40.0f;
|
|
|
|
m_fStopDistance = 0.0f;
|
|
|
|
m_fFlyCloseDistance = 12.5f*4;
|
|
|
|
m_fFlyStopDistance = 0.0f;
|
|
|
|
m_iScore = 10000;
|
|
|
|
}
|
|
|
|
m_fAttackFireTime = 3.0f;
|
|
|
|
m_fCloseFireTime = 2.0f;
|
|
|
|
m_fIgnoreRange = 200.0f;
|
|
|
|
// fly moving properties
|
|
|
|
m_fFlyWalkSpeed = FRnd()/2 + 2.0f;
|
|
|
|
m_aFlyWalkRotateSpeed = FRnd()*10.0f + 50.0f;
|
|
|
|
m_fFlyAttackRunSpeed = FRnd()*2.0f + 10.0f;
|
|
|
|
m_aFlyAttackRotateSpeed = FRnd()*75 + 350.0f;
|
|
|
|
m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.0f;
|
|
|
|
m_aFlyCloseRotateSpeed = FRnd()*50 + 600.0f;
|
|
|
|
// attack properties - CAN BE SET
|
|
|
|
m_fFlyAttackDistance = 100.0f;
|
|
|
|
m_fFlyAttackFireTime = 3.0f;
|
|
|
|
m_fFlyCloseFireTime = 2.0f;
|
|
|
|
m_fFlyIgnoreRange = 200.0f;
|
|
|
|
// damage/explode properties
|
|
|
|
m_fBlowUpAmount = 100.0f;
|
|
|
|
m_fBodyParts = 8;
|
|
|
|
// flame source
|
|
|
|
m_vFlameSource = FLOAT3D(0, 0, 0);
|
|
|
|
m_fGroundToAirSpeed = m_fFlyAttackRunSpeed;
|
|
|
|
m_fAirToGroundSpeed = m_fFlyAttackRunSpeed*2;
|
|
|
|
m_fAirToGroundMin = 0.1f;
|
|
|
|
m_fAirToGroundMax = 0.1f;
|
|
|
|
|
|
|
|
// continue behavior in base class
|
|
|
|
jump CEnemyFly::MainLoop();
|
|
|
|
};
|
|
|
|
};
|