mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-25 23:24:51 +01:00
221 lines
7.7 KiB
C++
221 lines
7.7 KiB
C++
/* 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. */
|
|
|
|
// WARNING: probable sync bads, doesn't work right
|
|
|
|
349
|
|
%{
|
|
#include "StdH.h"
|
|
#include "ModelsMP/Enemies/AirElemental/ShockwaveBase.h"
|
|
#include "ModelsMP/Enemies/AirElemental/Shockwave.h"
|
|
%}
|
|
|
|
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;
|
|
}
|
|
};
|