mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-11-22 18:30:27 +01:00
274 lines
8.4 KiB
Erlang
274 lines
8.4 KiB
Erlang
|
/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */
|
||
|
|
||
|
213
|
||
|
%{
|
||
|
#include "StdH.h"
|
||
|
%}
|
||
|
|
||
|
uses "EntitiesMP/ModelHolder2";
|
||
|
uses "EntitiesMP/Projectile";
|
||
|
|
||
|
class CEruptor : CModelHolder2 {
|
||
|
name "Eruptor";
|
||
|
thumbnail "Thumbnails\\Eruptor.tbn";
|
||
|
features "HasName", "IsTargetable";
|
||
|
|
||
|
properties:
|
||
|
// stretch
|
||
|
10 FLOAT m_fStretchAll "Er StretchAll" = 1.0f,
|
||
|
11 FLOAT m_fStretchX "Er StretchX" = 1.0f,
|
||
|
12 FLOAT m_fStretchY "Er StretchY" = 1.0f,
|
||
|
13 FLOAT m_fStretchZ "Er StretchZ" = 1.0f,
|
||
|
|
||
|
// random stretch
|
||
|
15 BOOL m_bRandomStretch "Er Stretch Random" = FALSE, // random stretch
|
||
|
16 FLOAT m_fStretchHeight "Er Stretch Height (Y%)" = 0.2f, // stretch height
|
||
|
17 FLOAT m_fStretchWidth "Er Stretch Width (X%)" = 0.2f, // stretch width
|
||
|
18 FLOAT m_fStretchDepth "Er Stretch Depth (Z%)" = 0.2f, // strecth depth
|
||
|
|
||
|
// spawn properties
|
||
|
20 FLOAT m_fAngle "Er Angle" 'Q' = 45.0f, // spawn spatial angle
|
||
|
21 FLOAT m_fMaxSpeed "Er Speed max" 'V' = 20.0f, // max speed
|
||
|
22 FLOAT m_fMinSpeed "Er Speed min" 'B' = 10.0f, // min speed
|
||
|
23 FLOAT m_fTime "Er Spawn time" 'F' = 1.0f, // spawn every x seconds
|
||
|
24 FLOAT m_fRandomWait "Er Random wait" 'G' = 0.0f, // wait between two spawns
|
||
|
25 enum ProjectileType m_ptType "Er Type" 'T' = PRT_LAVA_COMET,
|
||
|
26 BOOL m_bShootInArc "Er Shoot In Arc" 'S' = TRUE,
|
||
|
|
||
|
27 FLOAT m_fProjectileStretch "Er projectile stretch" = 1.0f, // strecth
|
||
|
|
||
|
components:
|
||
|
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
|
||
|
|
||
|
functions:
|
||
|
void Precache(void) {
|
||
|
PrecacheClass(CLASS_PROJECTILE, m_ptType);
|
||
|
}
|
||
|
|
||
|
/* calculates launch velocity and heading correction for angular launch */
|
||
|
void CalculateAngularLaunchParams(
|
||
|
CMovableEntity *penTarget,
|
||
|
FLOAT3D vShooting,
|
||
|
FLOAT3D vTarget, FLOAT3D vSpeedDest,
|
||
|
ANGLE aPitch,
|
||
|
ANGLE &aHeading,
|
||
|
FLOAT &fLaunchSpeed)
|
||
|
{
|
||
|
FLOAT3D vNewTarget = vTarget;
|
||
|
FLOAT3D &vGravity = penTarget->en_vGravityDir;
|
||
|
FLOAT fa = TanFast(AngleDeg(aPitch));
|
||
|
FLOAT3D vd, vyd0;
|
||
|
FLOAT fd, fyd0;
|
||
|
FLOAT fTime = 0.0f;
|
||
|
FLOAT fLastTime = 0.0f;
|
||
|
|
||
|
INDEX iIterations = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
iIterations++;
|
||
|
FLOAT3D vDistance = vNewTarget-vShooting;
|
||
|
GetParallelAndNormalComponents(vDistance, vGravity, vyd0, vd);
|
||
|
fd = vd.Length();
|
||
|
fyd0 = vyd0.Length();
|
||
|
fLastTime=fTime;
|
||
|
fTime = Sqrt(2.0f)*Sqrt((fa*fd-fyd0)/penTarget->en_fGravityA);
|
||
|
vNewTarget = vTarget+vSpeedDest*fTime;
|
||
|
}
|
||
|
while( Abs(fTime-fLastTime) > _pTimer->TickQuantum && iIterations<10);
|
||
|
|
||
|
// calculate launch speed
|
||
|
fLaunchSpeed = 0.707108f*fd/
|
||
|
(Cos(AngleDeg(aPitch))*Sqrt((fa*fd-fyd0)/penTarget->en_fGravityA));
|
||
|
// calculate heading correction
|
||
|
FLOAT3D vDir = (vNewTarget-vShooting).Normalize();
|
||
|
ANGLE3D aAngles;
|
||
|
DirectionVectorToAngles(vDir, aAngles);
|
||
|
aHeading = aAngles(1);
|
||
|
}
|
||
|
|
||
|
// spawn one projectile towards the target
|
||
|
void SpawnShoot(CEntity *penTarget)
|
||
|
{
|
||
|
// if not movable entity
|
||
|
if (penTarget==NULL || !(penTarget->GetPhysicsFlags()&EPF_MOVABLE)) {
|
||
|
// do nothing
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CPlacement3D plLava = GetPlacement();
|
||
|
|
||
|
FLOAT fSpeed = (m_fMaxSpeed-m_fMinSpeed)*FRnd() + m_fMinSpeed;
|
||
|
|
||
|
// if shootind with free falling projectile
|
||
|
if (m_bShootInArc) {
|
||
|
// calculate speed for angular launch
|
||
|
FLOAT fPitch = GetPlacement().pl_OrientationAngle(2);
|
||
|
FLOAT fHeading;
|
||
|
CalculateAngularLaunchParams((CMovableEntity*)penTarget,
|
||
|
GetPlacement().pl_PositionVector,
|
||
|
penTarget->GetPlacement().pl_PositionVector,
|
||
|
((CMovableEntity*)penTarget)->en_vCurrentTranslationAbsolute,
|
||
|
fPitch, fHeading, fSpeed);
|
||
|
|
||
|
// if the heading is out of range
|
||
|
if (Abs(NormalizeAngle(GetPlacement().pl_OrientationAngle(1)-fHeading)) >m_fAngle) {
|
||
|
// do nothing
|
||
|
return;
|
||
|
}
|
||
|
plLava.pl_OrientationAngle(1) = fHeading;
|
||
|
// if shootind with propelled projectile
|
||
|
} else {
|
||
|
// calculate direction
|
||
|
FLOAT3D vTargetDir = (penTarget->GetPlacement().pl_PositionVector-
|
||
|
GetPlacement().pl_PositionVector).Normalize();
|
||
|
FLOAT3D vShootDir;
|
||
|
AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vShootDir);
|
||
|
|
||
|
// if the heading is out of range
|
||
|
if (Abs(vTargetDir%vShootDir) < Cos(m_fAngle)) {
|
||
|
// do nothing
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DirectionVectorToAngles(vTargetDir, plLava.pl_OrientationAngle);
|
||
|
}
|
||
|
|
||
|
// create lava
|
||
|
SpawnProjectile(plLava, fSpeed);
|
||
|
}
|
||
|
|
||
|
// spawn one projectile in random direction
|
||
|
void SpawnRandom(void)
|
||
|
{
|
||
|
// generate speed
|
||
|
FLOAT fSpeed = (m_fMaxSpeed-m_fMinSpeed)*FRnd() + m_fMinSpeed;
|
||
|
ANGLE3D aAngle((FRnd()*2-1)*m_fAngle, (FRnd()*2-1)*m_fAngle, 0);
|
||
|
// create placement
|
||
|
CPlacement3D plLava(FLOAT3D(0, 0, 0), aAngle);
|
||
|
plLava.RelativeToAbsolute(GetPlacement());
|
||
|
|
||
|
SpawnProjectile(plLava, fSpeed);
|
||
|
}
|
||
|
|
||
|
// fire projectile in given direction with given speed
|
||
|
void SpawnProjectile(const CPlacement3D &pl, FLOAT fSpeed)
|
||
|
{
|
||
|
CEntityPointer penLava = CreateEntity(pl, CLASS_PROJECTILE);
|
||
|
|
||
|
// launch
|
||
|
ELaunchProjectile eLaunch;
|
||
|
eLaunch.penLauncher = this;
|
||
|
eLaunch.prtType = m_ptType;
|
||
|
eLaunch.fSpeed = fSpeed;
|
||
|
eLaunch.fStretch=m_fProjectileStretch;
|
||
|
penLava->Initialize(eLaunch);
|
||
|
|
||
|
// stretch
|
||
|
if (!(penLava->GetFlags()&ENF_DELETED)) {
|
||
|
FLOAT3D fStretchRandom(1, 1, 1);
|
||
|
if (m_bRandomStretch) {
|
||
|
fStretchRandom(1) = (FRnd()*m_fStretchWidth *2 - m_fStretchWidth ) + 1;
|
||
|
fStretchRandom(2) = (FRnd()*m_fStretchHeight*2 - m_fStretchHeight) + 1;
|
||
|
fStretchRandom(3) = (FRnd()*m_fStretchDepth *2 - m_fStretchDepth ) + 1;
|
||
|
}
|
||
|
FLOAT3D vOldStretch = penLava->GetModelObject()->mo_Stretch;
|
||
|
penLava->GetModelObject()->mo_Stretch = FLOAT3D(
|
||
|
m_fStretchAll*m_fStretchX*fStretchRandom(1)*vOldStretch(1),
|
||
|
m_fStretchAll*m_fStretchY*fStretchRandom(2)*vOldStretch(2),
|
||
|
m_fStretchAll*m_fStretchZ*fStretchRandom(3)*vOldStretch(3));
|
||
|
penLava->ModelChangeNotify();
|
||
|
}
|
||
|
}
|
||
|
procedures:
|
||
|
/************************************************************
|
||
|
* A C T I O N S *
|
||
|
************************************************************/
|
||
|
// active state
|
||
|
Active(EVoid)
|
||
|
{
|
||
|
wait() {
|
||
|
on (EBegin) : { call AutoSpawns(); }
|
||
|
on (EEnvironmentStop) : { jump Inactive(); }
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// inactive state
|
||
|
Inactive(EVoid)
|
||
|
{
|
||
|
wait() {
|
||
|
on (EBegin) : { resume; }
|
||
|
on (EEnvironmentStart) : { jump Active(); }
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// spawn projectiles automatically
|
||
|
AutoSpawns(EVoid)
|
||
|
{
|
||
|
while (TRUE) {
|
||
|
// wait before spawn next
|
||
|
autowait(m_fTime);
|
||
|
|
||
|
// spawn one projectile
|
||
|
SpawnRandom();
|
||
|
|
||
|
// random wait
|
||
|
if (m_fRandomWait > 0.0f) { autowait(m_fRandomWait); }
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
/************************************************************
|
||
|
* M A I N L O O P *
|
||
|
************************************************************/
|
||
|
// main loop
|
||
|
MainLoop(EVoid) {
|
||
|
wait() {
|
||
|
on(EBegin) : {
|
||
|
call Inactive();
|
||
|
};
|
||
|
on(ETrigger eTrigger) : {
|
||
|
SpawnShoot(eTrigger.penCaused);
|
||
|
resume;
|
||
|
}
|
||
|
otherwise() : {resume;};
|
||
|
}
|
||
|
|
||
|
// cease to exist
|
||
|
Destroy();
|
||
|
|
||
|
return;
|
||
|
};
|
||
|
|
||
|
Main(EVoid) {
|
||
|
// init as model
|
||
|
CModelHolder2::InitModelHolder();
|
||
|
|
||
|
// limit values
|
||
|
if (m_fTime <= 0.0f) { m_fTime = 0.05f; }
|
||
|
if (m_fMaxSpeed < m_fMinSpeed) { m_fMaxSpeed = m_fMinSpeed; }
|
||
|
if (m_fAngle < 0.0f) { m_fAngle = 0.0f; }
|
||
|
|
||
|
// stretch factors must not have extreme values
|
||
|
if (Abs(m_fStretchX) < 0.01f) { m_fStretchX = 0.01f; }
|
||
|
if (Abs(m_fStretchY) < 0.01f) { m_fStretchY = 0.01f; }
|
||
|
if (Abs(m_fStretchZ) < 0.01f) { m_fStretchZ = 0.01f; }
|
||
|
if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; }
|
||
|
|
||
|
if (Abs(m_fStretchX) >100.0f) { m_fStretchX = 100.0f*Sgn(m_fStretchX); }
|
||
|
if (Abs(m_fStretchY) >100.0f) { m_fStretchY = 100.0f*Sgn(m_fStretchY); }
|
||
|
if (Abs(m_fStretchZ) >100.0f) { m_fStretchZ = 100.0f*Sgn(m_fStretchZ); }
|
||
|
if (m_fStretchAll>100.0f) { m_fStretchAll = 100.0f; }
|
||
|
|
||
|
if (m_fStretchWidth <0.0f) { m_fStretchWidth = 0.0f; };
|
||
|
if (m_fStretchHeight<0.0f) { m_fStretchHeight = 0.0f; };
|
||
|
if (m_fStretchDepth <0.0f) { m_fStretchDepth = 0.0f; };
|
||
|
if (m_fStretchWidth >1.0f) { m_fStretchWidth = 1.0f; };
|
||
|
if (m_fStretchHeight>1.0f) { m_fStretchHeight = 1.0f; };
|
||
|
if (m_fStretchDepth >1.0f) { m_fStretchDepth = 1.0f; };
|
||
|
|
||
|
jump MainLoop();
|
||
|
}
|
||
|
};
|