Serious-Engine/Sources/EntitiesMP/AirShockwave.es

221 lines
7.8 KiB
C++
Raw Normal View History

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
// WARNING: probable sync bads, doesn't work right
349
%{
2016-04-01 20:04:24 +02:00
#include "EntitiesMP/StdH/StdH.h"
#include "ModelsMP/Enemies/AirElemental/ShockWaveBase.h"
#include "ModelsMP/Enemies/AirElemental/ShockWave.h"
2016-03-11 14:57:17 +01:00
%}
uses "EntitiesMP/BasicEffects";
// input parameter for launching the projectile
event EAirShockwave {
CEntityPointer penLauncher, // who launched it
FLOAT fHeight, // height in the beginning
FLOAT fEndWidth, // width along the X,Z axes in the end
FLOAT fDuration, // how long to live
};
%{
// shockwave
#define ECF_SHOCKAWAVE ( \
((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_TEST) |\
((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_PASS) |\
((ECBI_MODEL)<<ECB_IS))
#define EPF_SHOCKAWAVE ( \
EPF_ONBLOCK_STOP|EPF_ORIENTEDBYGRAVITY|EPF_ABSOLUTETRANSLATE)
#define SHOCKWAVE_HEIGHT 5.0f
#define SHOCKWAVE_WIDTH 0.1f
%}
class CAirShockwave : CMovableModelEntity {
name "AirShockwave";
thumbnail "";
properties:
1 CEntityPointer m_penLauncher, // who lanuched it
2 FLOAT m_fHeight = 0.0f, // beginning stretch
3 FLOAT m_fEndWidth = 0.0f, // ending stretch along the X,Z axes
4 FLOAT m_tmBegin = 0.0f, // time when animation began
5 FLOAT m_tmEnd = 0.0f, // time to destroy
6 FLOAT m_fDuration = 0.0f, // how long?
7 BOOL m_bGrowing = FALSE, // are we growing?
8 FLOAT m_tmLastGrow = 0.0f, // last grow time
9 FLOAT m_fFadeStartTime = 0.0f, // when the fading started
10 FLOAT m_fFadeStartPercent = 0.6f, // when to start the fading
// internal variables
20 FLOAT m_fStretchY = 0.0f,
21 FLOAT m_fBeginStretchXZ = 0.0f,
22 FLOAT m_fEndStretchXZ = 0.0f,
25 FLOATaabbox3D m_boxMaxSize = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(1,1,1)),
30 BOOL m_bFadeOut = FALSE, // set this when fading out
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
10 model MODEL_INVISIBLE "ModelsMP\\Enemies\\AirElemental\\ShockwaveBase.mdl",
11 model MODEL_SHOCKWAVE "ModelsMP\\Enemies\\AirElemental\\Shockwave.mdl",
12 texture TEXTURE_SHOCKWAVE "ModelsMP\\Enemies\\AirElemental\\Twister.tex",
functions:
// get the attachment that IS the AirShockwave
CModelObject *ShockwaveModel(void) {
CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE);
return &(amo0.amo_moModelObject);
};
// per-frame adjustments here
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) {
// growing
if (m_bGrowing) {
FLOAT3D vSize;
FLOAT fLifeTime = _pTimer->GetLerpedCurrentTick() - m_tmBegin;
vSize(1) = (fLifeTime/m_fDuration)*(m_fEndStretchXZ-m_fBeginStretchXZ)+m_fBeginStretchXZ;
vSize(2) = m_fStretchY;
vSize(3) = vSize(1);
ShockwaveModel()->StretchModel(vSize);
// start fadeout if more than 70% of lifetime passed
if ((fLifeTime/m_fDuration)>m_fFadeStartPercent && !m_bFadeOut) {
m_bFadeOut = TRUE;
m_fFadeStartTime = _pTimer->GetLerpedCurrentTick();
}
// remember last grow time
m_tmLastGrow = _pTimer->GetLerpedCurrentTick();
}
// fading out
if (m_bFadeOut) {
FLOAT fTimeRemain = m_tmEnd - _pTimer->GetLerpedCurrentTick();
FLOAT fFadeTime = (1 - m_fFadeStartPercent)*m_fDuration;
if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; }
COLOR colAlpha = ShockwaveModel()->mo_colBlendColor;
colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/fFadeTime*0xff)&0xff);
ShockwaveModel()->mo_colBlendColor = colAlpha;
}
return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
};
// throw away an entity when touched
void LaunchEntity(CEntity *pen) {
// don't launch air elemental and twisters and shockwaves and any items
if (IsOfClass(pen, "AirElemental") || IsOfClass(pen, "Twister")
|| IsDerivedFromClass(pen, "Item") || IsOfClass(pen, "AirShockwave")) {
return;
}
if (pen->GetPhysicsFlags()&EPF_MOVABLE) {
FLOAT3D vSpeed;
vSpeed = pen->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector;
if (vSpeed(2)<vSpeed.Length()*0.5f) { vSpeed(2)=vSpeed.Length()*0.5f; }
vSpeed.Normalize();
vSpeed = vSpeed*50.0f;
((CMovableEntity &)*pen).GiveImpulseTranslationAbsolute(vSpeed);
}
};
void TestForCollisionAndLaunchEntity() {
// test the bounding box for all colliding entities
static CStaticStackArray<CEntity *> apenNearEntities;
FLOAT fLifeTime = _pTimer->CurrentTick() - m_tmBegin;
FLOAT fCurrentRadius = Lerp(SHOCKWAVE_WIDTH, m_fEndWidth, fLifeTime/m_fDuration)/2.0f;
FLOATaabbox3D m_boxCurrent = m_boxMaxSize;
m_boxCurrent += GetPlacement().pl_PositionVector;
// width of 'launch belt'
FLOAT fBeltWidth = m_fEndWidth*_pTimer->TickQuantum*2.0f/m_fDuration;
GetWorld()->FindEntitiesNearBox(m_boxCurrent, apenNearEntities);
for (INDEX i=0; i<apenNearEntities.Count(); i++)
{
FLOAT fDistance = DistanceTo(this, apenNearEntities[i]);
FLOATaabbox3D m_boxEntity;
apenNearEntities[i]->GetBoundingBox(m_boxEntity);
if (fDistance<(fCurrentRadius+fBeltWidth/2.0f) && fDistance>(fCurrentRadius-fBeltWidth/2.0f) &&
m_boxEntity.HasContactWith(m_boxCurrent)) {
LaunchEntity(apenNearEntities[i]);
}
}
CMovableModelEntity::PreMoving();
};
procedures:
// --->>> MAIN
Main(EAirShockwave eas) {
// remember the initial parameters
ASSERT(eas.penLauncher!=NULL);
ASSERT(eas.fHeight>0.0f);
ASSERT(eas.fEndWidth>0.1f);
ASSERT(eas.fDuration>0.0f);
m_penLauncher = eas.penLauncher;
m_fHeight = eas.fHeight;
m_fEndWidth = eas.fEndWidth;
m_fDuration = eas.fDuration;
// calculate stretches from parameters
m_fStretchY = m_fHeight/SHOCKWAVE_HEIGHT;
m_fBeginStretchXZ = 1.0f;
m_fEndStretchXZ = m_fEndWidth/SHOCKWAVE_WIDTH;
FLOAT3D v1 = FLOAT3D(-m_fEndWidth/2.0f, 0.0f, -m_fEndWidth/2.0f);
FLOAT3D v2 = FLOAT3D(+m_fEndWidth/2.0f, m_fHeight, +m_fEndWidth/2.0f);
m_boxMaxSize = FLOATaabbox3D(v1, v2);
// initialization
InitAsModel();
SetPhysicsFlags(EPF_SHOCKAWAVE);
SetCollisionFlags(ECF_SHOCKAWAVE);
SetFlags(GetFlags() | ENF_SEETHROUGH);
// set appearance
SetModel(MODEL_INVISIBLE);
AddAttachmentToModel(this, *GetModelObject(), SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE, MODEL_SHOCKWAVE, TEXTURE_SHOCKWAVE, 0, 0, 0);
GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
ModelChangeNotify();
ShockwaveModel()->StretchModel(FLOAT3D(m_fBeginStretchXZ, m_fStretchY, m_fBeginStretchXZ));
autowait(_pTimer->TickQuantum);
m_tmBegin = _pTimer->CurrentTick();
m_tmEnd = m_tmBegin + m_fDuration;
m_tmLastGrow = _pTimer->CurrentTick();
m_bGrowing = TRUE;
while(_pTimer->CurrentTick()<m_tmEnd)
{
autowait(_pTimer->TickQuantum);
TestForCollisionAndLaunchEntity();
}
// cease to exist
Destroy();
return;
}
};