507 %{ #include "Entities/StdH/StdH.h" #define ECF_TWISTER ( \ ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< do not use 10 FLOAT3D m_vDesiredPosition = FLOAT3D(0,0,0), 11 FLOAT3D m_vDesiredAngle = FLOAT3D(0,0,0), 12 FLOAT m_fStopTime = 0.0f, 13 FLOAT m_fActionRadius = 0.0f, 14 FLOAT m_fActionTime = 0.0f, 15 FLOAT m_fDiffMultiply = 0.0f, 16 FLOAT m_fUpMultiply = 0.0f, 20 BOOL m_bFadeOut = FALSE, 21 FLOAT m_fFadeStartTime = 0.0f, 22 FLOAT m_fFadeTime = 2.0f, components: // ********* TWISTER ********* 10 model MODEL_TWISTER "Models\\Enemies\\Elementals\\Twister.mdl", 11 texture TEXTURE_TWISTER "Models\\Enemies\\Elementals\\AirMan01.tex", functions: /* Entity info */ void *GetEntityInfo(void) { return &eiTwister; }; /* Receive damage */ void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) { return; }; /************************************************************ * FADE OUT * ************************************************************/ BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { if (m_bFadeOut) { FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick(); if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; } COLOR colAlpha = GetModelObject()->mo_colBlendColor; colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/m_fFadeTime*0xff)&0xff); GetModelObject()->mo_colBlendColor = colAlpha; } return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); }; /************************************************************ * MOVING FUNCTIONS * ************************************************************/ // calculate rotation void CalcHeadingRotation(ANGLE aWantedHeadingRelative, ANGLE &aRotation) { // normalize it to [-180,+180] degrees aWantedHeadingRelative = NormalizeAngle(aWantedHeadingRelative); // if desired position is left if (aWantedHeadingRelative < -ROTATE_SPEED*MOVE_FREQUENCY) { // start turning left aRotation = -ROTATE_SPEED; // if desired position is right } else if (aWantedHeadingRelative > ROTATE_SPEED*MOVE_FREQUENCY) { // start turning right aRotation = +ROTATE_SPEED; // if desired position is more-less ahead } else { aRotation = aWantedHeadingRelative/MOVE_FREQUENCY; } }; // calculate angle from position void CalcAngleFromPosition() { // find relative orientation towards the desired position m_vDesiredAngle = (m_vDesiredPosition - GetPlacement().pl_PositionVector).Normalize(); }; // rotate entity to desired angle void RotateToAngle() { // find relative heading towards the desired angle ANGLE aRotation; CalcHeadingRotation(GetRelativeHeading(m_vDesiredAngle), aRotation); // start rotating SetDesiredRotation(ANGLE3D(aRotation, 0, 0)); }; // move in direction void MoveInDirection() { RotateToAngle(); // determine translation speed FLOAT3D vTranslation(0.0f, 0.0f, 0.0f); vTranslation(3) = -MOVE_SPEED; // start moving SetDesiredTranslation(vTranslation); }; // move entity to desired position void MoveToPosition() { CalcAngleFromPosition(); MoveInDirection(); }; // rotate entity to desired position void RotateToPosition() { CalcAngleFromPosition(); RotateToAngle(); }; // stop moving entity void StopMoving() { StopRotating(); StopTranslating(); }; // stop rotating entity void StopRotating() { SetDesiredRotation(ANGLE3D(0, 0, 0)); }; // stop translating void StopTranslating() { SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); }; /************************************************************ * ATTACK SPECIFIC * ************************************************************/ void SpinEntity(CEntity *pen) { // don't spin air elemental and another twister if (!(IsOfClass(pen, "Elemental") && ((CElemental&)*pen).m_EetType==ELT_AIR) && !(IsOfClass(pen, "Twister"))) { if (pen->GetPhysicsFlags()&EPF_MOVABLE) { // throw target away FLOAT3D vSpeed; vSpeed = FLOAT3D(en_mRotation(1, 2), en_mRotation(2, 2), en_mRotation(3, 2)) * m_fUpMultiply; FLOAT3D vDiff = (pen->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector).Normalize(); vSpeed += (vDiff*m_fDiffMultiply) * pen->en_mRotation; // give absolute speed ((CMovableEntity&)*pen).en_vCurrentTranslationAbsolute = vSpeed; ((CMovableEntity&)*pen).en_aDesiredRotationRelative = ANGLE3D(180.0f, 0, 0); // damage FLOAT3D vDirection; AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection); InflictDirectDamage(pen, m_penOwner, DMT_IMPACT, 0.1f, GetPlacement().pl_PositionVector, vDirection); } } }; /************************************************************ * P R O C E D U R E S * ************************************************************/ procedures: // --->>> MAIN Main(ETwister et) { // remember the initial parameters ASSERT(et.penOwner!=NULL); m_penOwner = et.penOwner; m_EtsSize = et.EtsSize; // initialization InitAsModel(); SetPhysicsFlags(EPF_TWISTER); SetCollisionFlags(ECF_TWISTER); SetFlags(GetFlags() | ENF_SEETHROUGH); SetModel(MODEL_TWISTER); SetModelMainTexture(TEXTURE_TWISTER); // setup switch(m_EtsSize) { case TWS_SMALL: m_fActionRadius = 10; m_fActionTime = 10; m_fUpMultiply = 5.0f; m_fDiffMultiply = 1.0f; break; case TWS_BIG: m_fActionRadius = 15; m_fActionTime = 20; m_fUpMultiply = 10.0f; m_fDiffMultiply = 4.0f; GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); break; case TWS_LARGE: m_fActionRadius = 20; m_fActionTime = 30; m_fUpMultiply = 20.0f; m_fDiffMultiply = 16.0f; GetModelObject()->StretchModel(FLOAT3D(16.0f, 16.0f, 16.0f)); break; } ModelChangeNotify(); // start position m_vStartPosition = GetPlacement().pl_PositionVector; // move in range m_fStopTime = _pTimer->CurrentTick() + 10.0f; while(_pTimer->CurrentTick() < m_fStopTime) { // new destination FLOAT fR = FRnd()*10.0f; FLOAT fA = FRnd()*360.0f; m_vDesiredPosition = m_vStartPosition + FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR); while((m_vDesiredPosition - GetPlacement().pl_PositionVector).Length() > MOVE_SPEED*MOVE_FREQUENCY*2.0f && _pTimer->CurrentTick() < m_fStopTime) { MoveToPosition(); wait(MOVE_FREQUENCY) { on (EBegin) : { resume; } on (ETimer) : { stop; } on (EPass ep) : { if (ep.penOther->GetRenderType()&RT_MODEL && ep.penOther->GetPhysicsFlags()&EPF_MOVABLE) { SpinEntity(ep.penOther); } resume; } } } } // fade out m_fFadeStartTime = _pTimer->CurrentTick(); m_bFadeOut = TRUE; m_fFadeTime = 2.0f; autowait(m_fFadeTime); // cease to exist Destroy(); return; } };