Merge pull request #14 from ptitSeb/master

Preliminary support for The First Encounter
This commit is contained in:
Ryan C. Gordon 2016-04-11 22:59:05 -04:00
commit 56de02e4b8
176 changed files with 64883 additions and 297 deletions

2
.gitignore vendored
View File

@ -64,6 +64,8 @@ Sources/EntitiesMP/*.cpp
!Sources/EntitiesMP/StdH/*
Sources/Engine/Classes/*.h
Sources/Engine/Classes/*.cpp
Sources/Entities/*.h
Sources/Entities/*.cpp
# Other generated files:
Sources/Engine/Ska/smcScan.cpp

View File

@ -111,6 +111,16 @@ option(USE_TREMOR "Use Tremor instead of Vorbis" FALSE)
if (USE_TREMOR)
add_definitions(-DUSE_TREMOR=1)
endif()
option(TFE "Compile a The First Encounter version" FALSE)
if (TFE)
add_definitions(-DFIRST_ENCOUNTER=1)
set(MP "")
else()
set(MP "MP")
endif()
# !!! FIXME: I currently force this, but you shouldn't _have_ to.
add_definitions(-DSINGLE_THREADED=1)
@ -190,166 +200,302 @@ entity(Engine/Classes/PlayerEntity)
set(ENGINE_ENTITIES_CPP ${ENTITIES_CPP})
set(ENTITIES_CPP "")
entity(EntitiesMP/AirElemental)
entity(EntitiesMP/AirShockwave)
entity(EntitiesMP/AmmoItem)
entity(EntitiesMP/AmmoPack)
entity(EntitiesMP/AnimationChanger)
entity(EntitiesMP/AnimationHub)
entity(EntitiesMP/AreaMarker)
entity(EntitiesMP/ArmorItem)
entity(EntitiesMP/BackgroundViewer)
entity(EntitiesMP/BasicEffects)
entity(EntitiesMP/Beast)
entity(EntitiesMP/BigHead)
entity(EntitiesMP/BlendController)
entity(EntitiesMP/BloodSpray)
entity(EntitiesMP/Boneman)
entity(EntitiesMP/Bouncer)
entity(EntitiesMP/Bullet)
entity(EntitiesMP/Camera)
entity(EntitiesMP/CameraMarker)
entity(EntitiesMP/CannonBall)
entity(EntitiesMP/CannonRotating)
entity(EntitiesMP/CannonStatic)
entity(EntitiesMP/ChainsawFreak)
entity(EntitiesMP/Copier)
entity(EntitiesMP/Counter)
entity(EntitiesMP/CrateBus)
entity(EntitiesMP/CrateRider)
entity(EntitiesMP/CreditsHolder)
entity(EntitiesMP/Damager)
entity(EntitiesMP/Debris)
entity(EntitiesMP/DebugEntityStatesDisplay)
entity(EntitiesMP/Demon)
entity(EntitiesMP/DestroyableArchitecture)
entity(EntitiesMP/Devil)
entity(EntitiesMP/DevilMarker)
entity(EntitiesMP/DevilProjectile)
entity(EntitiesMP/DoorController)
entity(EntitiesMP/Dragonman)
entity(EntitiesMP/EffectMarker)
entity(EntitiesMP/Effector)
entity(EntitiesMP/Elemental)
entity(EntitiesMP/EnemyBase)
entity(EntitiesMP/EnemyCounter)
entity(EntitiesMP/EnemyDive)
entity(EntitiesMP/EnemyFly)
entity(EntitiesMP/EnemyMarker)
entity(EntitiesMP/EnemyRunInto)
entity(EntitiesMP/EnemySpawner)
entity(EntitiesMP/EnvironmentBase)
entity(EntitiesMP/EnvironmentMarker)
entity(EntitiesMP/EnvironmentParticlesHolder)
entity(EntitiesMP/Eruptor)
entity(EntitiesMP/ExotechLarva)
entity(EntitiesMP/ExotechLarvaBattery)
entity(EntitiesMP/ExotechLarvaCharger)
entity(EntitiesMP/Eyeman)
entity(EntitiesMP/Fireworks)
entity(EntitiesMP/Fish)
entity(EntitiesMP/Flame)
entity(EntitiesMP/FogMarker)
entity(EntitiesMP/Gizmo)
entity(EntitiesMP/Global)
entity(EntitiesMP/GradientMarker)
entity(EntitiesMP/GravityMarker)
entity(EntitiesMP/GravityRouter)
entity(EntitiesMP/Grunt)
entity(EntitiesMP/GruntSka)
entity(EntitiesMP/Guffy)
entity(EntitiesMP/HazeMarker)
entity(EntitiesMP/Headman)
entity(EntitiesMP/HealthItem)
entity(EntitiesMP/HudPicHolder)
entity(EntitiesMP/Item)
entity(EntitiesMP/KeyItem)
entity(EntitiesMP/LarvaOffspring)
entity(EntitiesMP/Light)
entity(EntitiesMP/Lightning)
entity(EntitiesMP/Marker)
entity(EntitiesMP/MessageHolder)
entity(EntitiesMP/MessageItem)
entity(EntitiesMP/MeteorShower)
entity(EntitiesMP/MirrorMarker)
entity(EntitiesMP/ModelDestruction)
entity(EntitiesMP/ModelHolder)
entity(EntitiesMP/ModelHolder2)
entity(EntitiesMP/ModelHolder3)
entity(EntitiesMP/MovingBrush)
entity(EntitiesMP/MovingBrushMarker)
entity(EntitiesMP/MusicChanger)
entity(EntitiesMP/MusicHolder)
entity(EntitiesMP/NavigationMarker)
entity(EntitiesMP/ParticlesHolder)
entity(EntitiesMP/Pendulum)
entity(EntitiesMP/PhotoAlbum)
entity(EntitiesMP/Pipebomb)
entity(EntitiesMP/Player)
entity(EntitiesMP/PlayerActionMarker)
entity(EntitiesMP/PlayerAnimator)
entity(EntitiesMP/PlayerMarker)
entity(EntitiesMP/PlayerView)
entity(EntitiesMP/PlayerWeapons)
entity(EntitiesMP/PlayerWeaponsEffects)
entity(EntitiesMP/PowerUpItem)
entity(EntitiesMP/Projectile)
entity(EntitiesMP/PyramidSpaceShip)
entity(EntitiesMP/PyramidSpaceShipMarker)
entity(EntitiesMP/Reminder)
entity(EntitiesMP/RollingStone)
entity(EntitiesMP/Santa)
entity(EntitiesMP/Scorpman)
entity(EntitiesMP/ScrollHolder)
entity(EntitiesMP/SeriousBomb)
entity(EntitiesMP/Ship)
entity(EntitiesMP/ShipMarker)
entity(EntitiesMP/Shooter)
entity(EntitiesMP/SoundHolder)
entity(EntitiesMP/SpawnerProjectile)
entity(EntitiesMP/Spinner)
entity(EntitiesMP/StormController)
entity(EntitiesMP/Summoner)
entity(EntitiesMP/SummonerMarker)
entity(EntitiesMP/Switch)
entity(EntitiesMP/TacticsChanger)
entity(EntitiesMP/TacticsHolder)
entity(EntitiesMP/Teleport)
entity(EntitiesMP/Terrain)
entity(EntitiesMP/TextFXHolder)
entity(EntitiesMP/TimeController)
entity(EntitiesMP/TouchField)
entity(EntitiesMP/Trigger)
entity(EntitiesMP/Twister)
entity(EntitiesMP/VoiceHolder)
entity(EntitiesMP/Walker)
entity(EntitiesMP/WatchPlayers)
entity(EntitiesMP/Watcher)
entity(EntitiesMP/Water)
entity(EntitiesMP/WeaponItem)
entity(EntitiesMP/Werebull)
entity(EntitiesMP/Woman)
entity(EntitiesMP/WorldBase)
entity(EntitiesMP/WorldLink)
entity(EntitiesMP/WorldSettingsController)
if(TFE)
entity(Entities/Acid)
entity(Entities/AirWave)
entity(Entities/AmmoItem)
entity(Entities/AmmoPack)
entity(Entities/AnimationChanger)
entity(Entities/AnimationHub)
entity(Entities/ArmorItem)
entity(Entities/BackgroundViewer)
entity(Entities/BasicEffects)
entity(Entities/Beast)
entity(Entities/BigHead)
entity(Entities/BlendController)
entity(Entities/BloodSpray)
entity(Entities/Boneman)
entity(Entities/Bouncer)
entity(Entities/Bullet)
entity(Entities/Camera)
entity(Entities/CameraMarker)
entity(Entities/CannonBall)
entity(Entities/Catman)
entity(Entities/Copier)
entity(Entities/Counter)
entity(Entities/CrateRider)
entity(Entities/CyborgBike)
entity(Entities/Cyborg)
entity(Entities/Damager)
entity(Entities/Debris)
entity(Entities/DestroyableArchitecture)
entity(Entities/Devil)
entity(Entities/DevilMarker)
entity(Entities/DevilProjectile)
entity(Entities/DoorController)
entity(Entities/Dragonman)
entity(Entities/EffectMarker)
entity(Entities/Effector)
entity(Entities/Elemental)
entity(Entities/EnemyBase)
entity(Entities/EnemyCounter)
entity(Entities/EnemyDive)
entity(Entities/EnemyFly)
entity(Entities/EnemyMarker)
entity(Entities/EnemyRunInto)
entity(Entities/EnemySpawner)
entity(Entities/EnvironmentBase)
entity(Entities/EnvironmentMarker)
entity(Entities/Eruptor)
entity(Entities/Eyeman)
entity(Entities/Fish)
entity(Entities/Fishman)
entity(Entities/Flame)
entity(Entities/FogMarker)
#entity(Entities/GhostBusterRay)
entity(Entities/Gizmo)
entity(Entities/Global)
entity(Entities/GradientMarker)
entity(Entities/GravityMarker)
entity(Entities/GravityRouter)
entity(Entities/HazeMarker)
entity(Entities/Headman)
entity(Entities/HealthItem)
entity(Entities/Huanman)
entity(Entities/Item)
entity(Entities/KeyItem)
entity(Entities/Light)
entity(Entities/Lightning)
entity(Entities/LightStyle)
entity(Entities/Mamut)
entity(Entities/Mamutman)
entity(Entities/Mantaman)
entity(Entities/Marker)
entity(Entities/MessageHolder)
entity(Entities/MessageItem)
entity(Entities/MirrorMarker)
entity(Entities/ModelDestruction)
entity(Entities/ModelHolder2)
entity(Entities/ModelHolder)
entity(Entities/MovingBrush)
entity(Entities/MovingBrushMarker)
entity(Entities/MusicChanger)
entity(Entities/MusicHolder)
entity(Entities/NavigationMarker)
entity(Entities/ParticlesHolder)
entity(Entities/Pendulum)
entity(Entities/Pipebomb)
entity(Entities/PlayerActionMarker)
entity(Entities/PlayerAnimator)
entity(Entities/Player)
entity(Entities/PlayerMarker)
entity(Entities/PlayerView)
entity(Entities/PlayerWeaponsEffects)
entity(Entities/PlayerWeapons)
entity(Entities/Projectile)
entity(Entities/PyramidSpaceShip)
entity(Entities/PyramidSpaceShipMarker)
entity(Entities/Reminder)
entity(Entities/RobotDriving)
entity(Entities/RobotFixed)
entity(Entities/RobotFlying)
entity(Entities/RollingStone)
entity(Entities/Scorpman)
entity(Entities/Ship)
entity(Entities/ShipMarker)
entity(Entities/SoundHolder)
entity(Entities/StormController)
entity(Entities/Switch)
entity(Entities/Teleport)
entity(Entities/TouchField)
entity(Entities/Trigger)
entity(Entities/Twister)
entity(Entities/VoiceHolder)
entity(Entities/Walker)
entity(Entities/Watcher)
entity(Entities/WatchPlayers)
entity(Entities/Water)
entity(Entities/WeaponItem)
entity(Entities/Werebull)
entity(Entities/Woman)
entity(Entities/WorldBase)
entity(Entities/WorldLink)
entity(Entities/WorldSettingsController)
else()
entity(EntitiesMP/AirElemental)
entity(EntitiesMP/AirShockwave)
entity(EntitiesMP/AmmoItem)
entity(EntitiesMP/AmmoPack)
entity(EntitiesMP/AnimationChanger)
entity(EntitiesMP/AnimationHub)
entity(EntitiesMP/AreaMarker)
entity(EntitiesMP/ArmorItem)
entity(EntitiesMP/BackgroundViewer)
entity(EntitiesMP/BasicEffects)
entity(EntitiesMP/Beast)
entity(EntitiesMP/BigHead)
entity(EntitiesMP/BlendController)
entity(EntitiesMP/BloodSpray)
entity(EntitiesMP/Boneman)
entity(EntitiesMP/Bouncer)
entity(EntitiesMP/Bullet)
entity(EntitiesMP/Camera)
entity(EntitiesMP/CameraMarker)
entity(EntitiesMP/CannonBall)
entity(EntitiesMP/CannonRotating)
entity(EntitiesMP/CannonStatic)
entity(EntitiesMP/ChainsawFreak)
entity(EntitiesMP/Copier)
entity(EntitiesMP/Counter)
entity(EntitiesMP/CrateBus)
entity(EntitiesMP/CrateRider)
entity(EntitiesMP/CreditsHolder)
entity(EntitiesMP/Damager)
entity(EntitiesMP/Debris)
entity(EntitiesMP/DebugEntityStatesDisplay)
entity(EntitiesMP/Demon)
entity(EntitiesMP/DestroyableArchitecture)
entity(EntitiesMP/Devil)
entity(EntitiesMP/DevilMarker)
entity(EntitiesMP/DevilProjectile)
entity(EntitiesMP/DoorController)
entity(EntitiesMP/Dragonman)
entity(EntitiesMP/EffectMarker)
entity(EntitiesMP/Effector)
entity(EntitiesMP/Elemental)
entity(EntitiesMP/EnemyBase)
entity(EntitiesMP/EnemyCounter)
entity(EntitiesMP/EnemyDive)
entity(EntitiesMP/EnemyFly)
entity(EntitiesMP/EnemyMarker)
entity(EntitiesMP/EnemyRunInto)
entity(EntitiesMP/EnemySpawner)
entity(EntitiesMP/EnvironmentBase)
entity(EntitiesMP/EnvironmentMarker)
entity(EntitiesMP/EnvironmentParticlesHolder)
entity(EntitiesMP/Eruptor)
entity(EntitiesMP/ExotechLarva)
entity(EntitiesMP/ExotechLarvaBattery)
entity(EntitiesMP/ExotechLarvaCharger)
entity(EntitiesMP/Eyeman)
entity(EntitiesMP/Fireworks)
entity(EntitiesMP/Fish)
entity(EntitiesMP/Flame)
entity(EntitiesMP/FogMarker)
entity(EntitiesMP/Gizmo)
entity(EntitiesMP/Global)
entity(EntitiesMP/GradientMarker)
entity(EntitiesMP/GravityMarker)
entity(EntitiesMP/GravityRouter)
entity(EntitiesMP/Grunt)
entity(EntitiesMP/GruntSka)
entity(EntitiesMP/Guffy)
entity(EntitiesMP/HazeMarker)
entity(EntitiesMP/Headman)
entity(EntitiesMP/HealthItem)
entity(EntitiesMP/HudPicHolder)
entity(EntitiesMP/Item)
entity(EntitiesMP/KeyItem)
entity(EntitiesMP/LarvaOffspring)
entity(EntitiesMP/Light)
entity(EntitiesMP/Lightning)
entity(EntitiesMP/Marker)
entity(EntitiesMP/MessageHolder)
entity(EntitiesMP/MessageItem)
entity(EntitiesMP/MeteorShower)
entity(EntitiesMP/MirrorMarker)
entity(EntitiesMP/ModelDestruction)
entity(EntitiesMP/ModelHolder)
entity(EntitiesMP/ModelHolder2)
entity(EntitiesMP/ModelHolder3)
entity(EntitiesMP/MovingBrush)
entity(EntitiesMP/MovingBrushMarker)
entity(EntitiesMP/MusicChanger)
entity(EntitiesMP/MusicHolder)
entity(EntitiesMP/NavigationMarker)
entity(EntitiesMP/ParticlesHolder)
entity(EntitiesMP/Pendulum)
entity(EntitiesMP/PhotoAlbum)
entity(EntitiesMP/Pipebomb)
entity(EntitiesMP/Player)
entity(EntitiesMP/PlayerActionMarker)
entity(EntitiesMP/PlayerAnimator)
entity(EntitiesMP/PlayerMarker)
entity(EntitiesMP/PlayerView)
entity(EntitiesMP/PlayerWeapons)
entity(EntitiesMP/PlayerWeaponsEffects)
entity(EntitiesMP/PowerUpItem)
entity(EntitiesMP/Projectile)
entity(EntitiesMP/PyramidSpaceShip)
entity(EntitiesMP/PyramidSpaceShipMarker)
entity(EntitiesMP/Reminder)
entity(EntitiesMP/RollingStone)
entity(EntitiesMP/Santa)
entity(EntitiesMP/Scorpman)
entity(EntitiesMP/ScrollHolder)
entity(EntitiesMP/SeriousBomb)
entity(EntitiesMP/Ship)
entity(EntitiesMP/ShipMarker)
entity(EntitiesMP/Shooter)
entity(EntitiesMP/SoundHolder)
entity(EntitiesMP/SpawnerProjectile)
entity(EntitiesMP/Spinner)
entity(EntitiesMP/StormController)
entity(EntitiesMP/Summoner)
entity(EntitiesMP/SummonerMarker)
entity(EntitiesMP/Switch)
entity(EntitiesMP/TacticsChanger)
entity(EntitiesMP/TacticsHolder)
entity(EntitiesMP/Teleport)
entity(EntitiesMP/Terrain)
entity(EntitiesMP/TextFXHolder)
entity(EntitiesMP/TimeController)
entity(EntitiesMP/TouchField)
entity(EntitiesMP/Trigger)
entity(EntitiesMP/Twister)
entity(EntitiesMP/VoiceHolder)
entity(EntitiesMP/Walker)
entity(EntitiesMP/WatchPlayers)
entity(EntitiesMP/Watcher)
entity(EntitiesMP/Water)
entity(EntitiesMP/WeaponItem)
entity(EntitiesMP/Werebull)
entity(EntitiesMP/Woman)
entity(EntitiesMP/WorldBase)
entity(EntitiesMP/WorldLink)
entity(EntitiesMP/WorldSettingsController)
endif()
add_custom_target(ParseEntities DEPENDS ${ENTITIES_H})
set(ENTITIESMPLIB "EntitiesMP${DEBUGSUFFIX}")
add_library(${ENTITIESMPLIB} SHARED
${ENTITIES_CPP}
EntitiesMP/Common/Common.cpp
EntitiesMP/Common/Particles.cpp
EntitiesMP/Common/EmanatingParticles.cpp
EntitiesMP/Common/PathFinding.cpp
EntitiesMP/Common/HUD.cpp
)
set(ENTITIESMPLIB "Entities${MP}${DEBUGSUFFIX}")
if(TFE)
add_library(${ENTITIESMPLIB} SHARED
${ENTITIES_CPP}
Entities/Common/Common.cpp
Entities/Common/Debris.cpp
Entities/Common/Particles.cpp
Entities/Common/Stats.cpp
Entities/Common/PathFinding.cpp
Entities/Common/HUD.cpp
)
else()
add_library(${ENTITIESMPLIB} SHARED
${ENTITIES_CPP}
EntitiesMP/Common/Common.cpp
EntitiesMP/Common/Particles.cpp
EntitiesMP/Common/EmanatingParticles.cpp
EntitiesMP/Common/PathFinding.cpp
EntitiesMP/Common/HUD.cpp
)
endif()
if(MACOSX)
target_link_libraries(${ENTITIESMPLIB} "-undefined dynamic_lookup")
endif()
add_dependencies(${ENTITIESMPLIB} ParseEntities)
set(GAMEMPLIB "GameMP${DEBUGSUFFIX}")
set(GAMEMPLIB "Game${MP}${DEBUGSUFFIX}")
add_library(${GAMEMPLIB} SHARED
GameMP/Camera.cpp
GameMP/CompMessage.cpp
@ -666,5 +812,9 @@ if(LINUX)
endif()
endif()
if(TFE)
set_target_properties(ssam PROPERTIES OUTPUT_NAME "ssam-tfe")
endif()
# end of CMakeLists.txt ...

6
Sources/Engine/Base/CTString.cpp Normal file → Executable file
View File

@ -638,8 +638,10 @@ BOOL CTString::Matches(const char *strOther) const
} else {
q = 0;
}
if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q)) {
// also, '\\' in mask should match '/' in name, for unix compatibility
if (((tolower(*m) != tolower(*n)) && ((*m!='\\') && (*n!='/')))
&& ((*m != '?') || q)) {
if (!wild) {
return FALSE;
}

2
Sources/Engine/Base/ProgressHook.cpp Normal file → Executable file
View File

@ -49,7 +49,7 @@ void CallProgressHook_t(FLOAT fCompleted)
bTimeInitialized = TRUE;
}
CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
if ((tvNow-tvLastUpdate) > CTimerValue(net_fSendRetryWait*1.1)) {
if ((tvNow-tvLastUpdate) > CTimerValue(net_fSendRetryWait*1.1f)) {
if (_pNetwork->ga_IsServer) {
// handle server messages
_cmiComm.Server_Update();

3
Sources/Engine/Base/SDL/SDLInput.cpp Normal file → Executable file
View File

@ -759,8 +759,11 @@ void CInput::GetInput(BOOL bPreScan)
return;
}
#if 0
// should not be usefull
SDL_Event event;
while (SE_SDL_InputEventPoll(&event)) { /* do nothing... */ }
#endif
// if not pre-scanning
if (!bPreScan) {

29
Sources/Engine/Light/LayerMixer.cpp Normal file → Executable file
View File

@ -57,7 +57,6 @@ extern INDEX shd_iDithering;
extern const UBYTE *pubClipByte;
extern UBYTE aubSqrt[ SQRTTABLESIZE];
extern UWORD auw1oSqrt[SQRTTABLESIZE];
extern UWORD auw1oSqrt[SQRTTABLESIZE];
// static FLOAT3D _v00;
// internal class for layer mixing
@ -123,7 +122,7 @@ public:
// add the intensity to the pixel
inline void AddToCluster( UBYTE *pub);
inline void AddAmbientToCluster( UBYTE *pub);
inline void AddToCluster( UBYTE *pub, FLOAT fIntensity);
inline void AddToCluster( UBYTE *pub, SLONG slIntensity);
// additional functions
__forceinline void CopyShadowLayer(void);
@ -161,11 +160,11 @@ inline void CLayerMixer::AddAmbientToCluster( UBYTE *pub)
IncrementByteWithClip(pub[1], ((UBYTE*)&lm_colAmbient)[2]);
IncrementByteWithClip(pub[2], ((UBYTE*)&lm_colAmbient)[1]);
}
inline void CLayerMixer::AddToCluster( UBYTE *pub, FLOAT fIntensity)
inline void CLayerMixer::AddToCluster( UBYTE *pub, SLONG slIntensity)
{
IncrementByteWithClip(pub[0], (long) (((UBYTE*)&lm_colLight)[3] *fIntensity));
IncrementByteWithClip(pub[1], (long) (((UBYTE*)&lm_colLight)[2] *fIntensity));
IncrementByteWithClip(pub[2], (long) (((UBYTE*)&lm_colLight)[1] *fIntensity));
IncrementByteWithClip(pub[0], (long) (((UBYTE*)&lm_colLight)[3] *slIntensity)>>16);
IncrementByteWithClip(pub[1], (long) (((UBYTE*)&lm_colLight)[2] *slIntensity)>>16);
IncrementByteWithClip(pub[2], (long) (((UBYTE*)&lm_colLight)[1] *slIntensity)>>16);
}
@ -464,9 +463,9 @@ skipPixel:
SLONG slL = (slL2Point>>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases
SLONG slIntensity = _slLightMax;
slL = aubSqrt[slL];
if( slL>_slHotSpot) slIntensity = ((255-slL)*_slLightStep)>>8;
if( slL>_slHotSpot) slIntensity = ((255-slL)*_slLightStep);
// add the intensity to the pixel
AddToCluster( pubLayer, slIntensity/255.0f);
AddToCluster( pubLayer, slIntensity);
}
// go to the next pixel
pubLayer+=4;
@ -682,9 +681,9 @@ skipPixel:
SLONG slL = (slL2Point>>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases
SLONG slIntensity = _slLightMax;
slL = aubSqrt[slL];
if( slL>_slHotSpot) slIntensity = ((255-slL)*_slLightStep)>>8;
if( slL>_slHotSpot) slIntensity = ((255-slL)*_slLightStep);
// add the intensity to the pixel
AddToCluster( pubLayer, slIntensity/255.0f);
AddToCluster( pubLayer, slIntensity);
}
// go to the next pixel
pubLayer+=4;
@ -899,9 +898,10 @@ skipPixel:
SLONG sl1oL = (slL2Point>>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases
sl1oL = auw1oSqrt[sl1oL];
SLONG slIntensity = _slLightMax;
if( sl1oL<slMax1oL) slIntensity = ((sl1oL-256)*_slLightStep)>>16;
if( sl1oL<256) slIntensity = 0;
else if( sl1oL<slMax1oL) slIntensity = ((sl1oL-256)*_slLightStep)/*>>16*/;
// add the intensity to the pixel
AddToCluster( pubLayer, slIntensity/255.0f);
AddToCluster( pubLayer, slIntensity);
}
// advance to next pixel
pubLayer+=4;
@ -1119,9 +1119,10 @@ skipPixel:
SLONG sl1oL = (slL2Point>>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases
sl1oL = auw1oSqrt[sl1oL];
SLONG slIntensity = _slLightMax;
if( sl1oL<slMax1oL) slIntensity = ((sl1oL-256)*_slLightStep)>>16;
if( sl1oL<256) slIntensity = 0;
else if( sl1oL<slMax1oL) slIntensity = ((sl1oL-256)*_slLightStep)/*>>16*/;
// add the intensity to the pixel
AddToCluster( pubLayer, slIntensity/255.0f);
AddToCluster( pubLayer, slIntensity);
}
// advance to next pixel
pubLayer+=4;

4
Sources/Engine/Math/Functions.h Normal file → Executable file
View File

@ -447,7 +447,11 @@ printf("CHECK THIS: %s:%d\n", __FILE__, __LINE__);
// square root (works with negative numbers)
#ifdef __arm__
inline FLOAT Sqrt( FLOAT x) { return sqrtf( ClampDn( x, 0.0f)); }
#else
inline FLOAT Sqrt( FLOAT x) { return (FLOAT)sqrt( ClampDn( x, 0.0f)); }
#endif

24
Sources/Engine/Math/Quaternion.h Normal file → Executable file
View File

@ -370,8 +370,8 @@ void Quaternion<Type>::FromEuler(const Vector<Type, 3> &a)
template<class Type>
Type Quaternion<Type>::EPS(Type orig) const
{
if ((orig <= 10e-6) && (orig >= -10e-6))
return(0.0);
if ((orig <= 10e-6f) && (orig >= -10e-6f))
return(0.0f);
return(orig);
}
@ -384,9 +384,9 @@ void Quaternion<Type>::ToMatrix(Matrix<Type, 3, 3> &m) const
Type yy = 2*q_y*q_y; Type yz = 2*q_y*q_z; Type zz = 2*q_z*q_z;
Type wx = 2*q_w*q_x; Type wy = 2*q_w*q_y; Type wz = 2*q_w*q_z;
m(1,1) = EPS(1.0-(yy+zz)); m(1,2) = EPS(xy-wz); m(1,3) = EPS(xz+wy);
m(2,1) = EPS(xy+wz); m(2,2) = EPS(1.0-(xx+zz)); m(2,3) = EPS(yz-wx);
m(3,1) = EPS(xz-wy); m(3,2) = EPS(yz+wx); m(3,3) = EPS(1.0-(xx+yy));
m(1,1) = EPS(1.0f-(yy+zz));m(1,2) = EPS(xy-wz); m(1,3) = EPS(xz+wy);
m(2,1) = EPS(xy+wz); m(2,2) = EPS(1.0f-(xx+zz));m(2,3) = EPS(yz-wx);
m(3,1) = EPS(xz-wy); m(3,2) = EPS(yz+wx); m(3,3) = EPS(1.0f-(xx+yy));
}
// conversion from matrix
@ -396,12 +396,12 @@ void Quaternion<Type>::FromMatrix(Matrix<Type, 3, 3> &m)
Type trace = m(1,1)+m(2,2)+m(3,3);
Type root;
if ( trace > 0.0 )
if ( trace > 0.0f )
{
// |w| > 1/2, may as well choose w > 1/2
root = sqrt(trace+1.0); // 2w
q_w = 0.5*root;
root = 0.5/root; // 1/(4w)
root = sqrt(trace+1.0f); // 2w
q_w = 0.5f*root;
root = 0.5f/root; // 1/(4w)
q_x = (m(3,2)-m(2,3))*root;
q_y = (m(1,3)-m(3,1))*root;
q_z = (m(2,1)-m(1,2))*root;
@ -418,10 +418,10 @@ void Quaternion<Type>::FromMatrix(Matrix<Type, 3, 3> &m)
int j = next[i];
int k = next[j];
root = sqrt(m(i+1,i+1)-m(j+1,j+1)-m(k+1,k+1)+1.0);
root = sqrt(m(i+1,i+1)-m(j+1,j+1)-m(k+1,k+1)+1.0f);
Type* quat[3] = { &q_x, &q_y, &q_z };
*quat[i] = 0.5*root;
root = 0.5/root;
*quat[i] = 0.5f*root;
root = 0.5f/root;
q_w = (m(k+1,j+1)-m(j+1,k+1))*root;
*quat[j] = (m(j+1,i+1)+m(i+1,j+1))*root;
*quat[k] = (m(k+1,i+1)+m(i+1,k+1))*root;

2
Sources/Engine/Math/Vector.h Normal file → Executable file
View File

@ -234,7 +234,7 @@ template<class Type, int iDimensions>
__forceinline Vector<Type, iDimensions> &Vector<Type, iDimensions>::SafeNormalize(void)
{
Type tLen = Length();
if (tLen<1E-6) {
if (tLen<1E-6f) {
if (iDimensions==2) {
*this = Vector(1,0);
} else {

4
Sources/Engine/Sound/SoundObject.h Normal file → Executable file
View File

@ -142,8 +142,8 @@ public:
// Set filter
inline void SetFilter( FLOAT fLeftFilter, FLOAT fRightFilter) { // 1=no filter (>1=more bass)
ASSERT( (fLeftFilter >= 1) && (fRightFilter >= 1));
so_spNew.sp_slLeftFilter = FloatToInt(32767.0/fLeftFilter);
so_spNew.sp_slRightFilter = FloatToInt(32767.0/fRightFilter);
so_spNew.sp_slLeftFilter = FloatToInt(32767.0f/fLeftFilter);
so_spNew.sp_slRightFilter = FloatToInt(32767.0f/fRightFilter);
};
// Set pitch shifting
inline void SetPitch( FLOAT fPitch) { // 1.0 for normal (<1 = slower, >1 = faster playing)

70
Sources/Entities/Acid.es Normal file
View File

@ -0,0 +1,70 @@
509
%{
#include "Entities/StdH/StdH.h"
%}
// input parameter for acid
event EAcid {
CEntityPointer penOwner, // entity which owns it
CEntityPointer penTarget, // target entity which receive damage
};
class CAcid : CMovableModelEntity {
name "Acid";
thumbnail "";
properties:
1 CEntityPointer m_penOwner, // entity which owns it
2 CEntityPointer m_penTarget, // target entity which receive damage
5 BOOL m_bLoop = FALSE, // internal for loops
components:
functions:
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
// --->>> MAIN
Main(EAcid ea) {
// attach to parent (another entity)
ASSERT(ea.penOwner!=NULL);
ASSERT(ea.penTarget!=NULL);
m_penOwner = ea.penOwner;
m_penTarget = ea.penTarget;
// initialization
InitAsVoid();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// acid damage
SpawnReminder(this, 10.0f, 0);
m_bLoop = TRUE;
while(m_bLoop) {
wait(0.25f) {
// damage to parent
on (EBegin) : {
// inflict damage to parent
if (m_penTarget!=NULL && !(m_penTarget->GetFlags()&ENF_DELETED)) {
m_penTarget->InflictDirectDamage(m_penTarget, m_penOwner, DMT_ACID, 0.25f, FLOAT3D(0, 0, 0), FLOAT3D(0, 0, 0));
// stop existing
} else {
m_bLoop = FALSE;
stop;
}
resume;
}
on (ETimer) : { stop; }
on (EReminder) : {
m_bLoop = FALSE;
stop;
}
}
}
// cease to exist
Destroy();
return;
}
};

151
Sources/Entities/AirWave.es Normal file
View File

@ -0,0 +1,151 @@
510
%{
#include "Entities/StdH/StdH.h"
#define ECF_AIRWAVE ( \
((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_TEST) |\
((ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_PASS) |\
((ECBI_MODEL)<<ECB_IS))
#define EPF_AIRWAVE ( \
EPF_ONBLOCK_SLIDE|EPF_MOVABLE|EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY)
%}
// input parameter for air wave
event EAirWave {
CEntityPointer penLauncher, // entity which launch it
};
%{
#define SLIDE_TIME 5.0f
%}
class CAirWave : CMovableModelEntity {
name "Air wave";
thumbnail "";
properties:
1 CEntityPointer m_penLauncher, // entity which launch it
// internal -> do not use
10 FLOAT m_fDamageAmount = 0.0f, // water hit damage
11 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored
12 FLOAT m_fStartTime = 0.0f, // projectile start time
components:
// ********* WATER *********
10 model MODEL_AIRWAVE "Models\\Enemies\\Mamut\\Projectile\\MamutProjectile.mdl",
11 texture TEXTURE_AIRWAVE "Models\\Enemies\\Mamut\\Projectile\\MamutProjectile.tex",
functions:
void PreMoving(void) {
// stretch model (1-9)
FLOAT3D vRatio = FLOAT3D(1, 1, 1);
vRatio *= 8*((_pTimer->CurrentTick()-m_fStartTime)/SLIDE_TIME)+1;
GetModelObject()->StretchModel(vRatio);
ModelChangeNotify();
CMovableModelEntity::PreMoving();
};
/************************************************************
* FADE OUT *
************************************************************/
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) {
FLOAT fTimeRemain = m_fStartTime + SLIDE_TIME - _pTimer->CurrentTick();
if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; }
COLOR colAlpha = GetModelObject()->mo_colBlendColor;
colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/SLIDE_TIME*0xff)&0xff);
GetModelObject()->mo_colBlendColor = colAlpha;
return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
};
/************************************************************
* ATTACK SPECIFIC *
************************************************************/
// air wave touch his valid target
void AirWaveTouch(CEntityPointer penHit) {
// time passed
FLOAT fTimeDiff = _pTimer->CurrentTick() - m_fStartTime;
FLOAT fRatio = (SLIDE_TIME - fTimeDiff) / 5.0f;
// direct damage
FLOAT3D vDirection;
AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection);
InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, 2.0f * fRatio,
GetPlacement().pl_PositionVector, vDirection);
// push target away
FLOAT3D vSpeed;
GetPitchDirection(90.0f, vSpeed);
vSpeed = vSpeed * 10.0f * fRatio;
KickEntity(penHit, vSpeed);
};
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
// --->>> PROJECTILE SLIDE ON BRUSH
AirWaveSlide(EVoid) {
m_fStartTime = _pTimer->CurrentTick();
LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher);
// fly loop
wait(SLIDE_TIME) {
on (EBegin) : { resume; }
on (EPass epass) : {
BOOL bHit;
// ignore launcher within 1 second
bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime;
if (bHit) {
AirWaveTouch(epass.penOther);
}
resume;
}
on (ETouch etouch) : {
// clear time limit for launcher
m_fIgnoreTime = 0.0f;
// air wave is moving to slow (stuck somewhere) -> kill it
if (en_vCurrentTranslationAbsolute.Length() < 0.25f*en_vDesiredTranslationRelative.Length()) {
stop;
}
resume;
}
on (EDeath) : { stop; }
on (ETimer) : { stop; }
}
return EEnd();
};
// --->>> MAIN
Main(EAirWave eaw) {
// remember the initial parameters
ASSERT(eaw.penLauncher!=NULL);
m_penLauncher = eaw.penLauncher;
// initialization
InitAsModel();
SetPhysicsFlags(EPF_AIRWAVE);
SetCollisionFlags(ECF_AIRWAVE);
SetModel(MODEL_AIRWAVE);
SetModelMainTexture(TEXTURE_AIRWAVE);
// remember lauching time
m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f;
// slide
autocall AirWaveSlide() EEnd;
// cease to exist
Destroy();
return;
}
};

View File

@ -0,0 +1,391 @@
803
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
#include "Models/Items/Ammo/Shells/Shells.h"
#include "Models/Items/Ammo/Bullets/Bullets.h"
#include "Models/Items/Ammo/Rockets/Rockets.h"
#include "Models/Weapons/RocketLauncher/Projectile/Rocket.h"
#include "Models/Items/Ammo/Grenades/Grenades.h"
#include "Models/Items/Ammo/Electricity/Electricity.h"
#include "Models/Items/Ammo/Cannonball/CannonBall.h"
#include "Models/Items/Ammo/Cannonball/CannonBallQuad.h"
%}
uses "Entities/Item";
// ammo type
enum AmmoItemType {
1 AIT_SHELLS "Shells",
2 AIT_BULLETS "Bullets",
3 AIT_ROCKETS "Rockets",
4 AIT_GRENADES "Grenades",
5 AIT_ELECTRICITY "Electricity",
6 AIT_NUKEBALL "obsolete",
7 AIT_IRONBALLS "IronBalls",
8 AIT_SERIOUSPACK "SeriousPack - don't use",
9 AIT_BACKPACK "BackPack - don't use",
10 AIT_NAPALM "obsolete",
};
// event for sending through receive item
event EAmmoItem {
enum AmmoItemType EaitType, // ammo type
INDEX iQuantity, // ammo quantity
};
class CAmmoItem : CItem {
name "Ammo Item";
thumbnail "Thumbnails\\AmmoItem.tbn";
properties:
1 enum AmmoItemType m_EaitType "Type" 'Y' = AIT_SHELLS, // health type
components:
0 class CLASS_BASE "Classes\\Item.ecl",
// ********* SHELLS *********
1 model MODEL_SHELLS "Models\\Items\\Ammo\\Shells\\Shells.mdl",
2 texture TEXTURE_SHELLS "Models\\Items\\Ammo\\Shells\\Shells.tex",
// ********* BULLETS *********
10 model MODEL_BULLETS "Models\\Items\\Ammo\\Bullets\\Bullets.mdl",
11 texture TEXTURE_BULLETS "Models\\Items\\Ammo\\Bullets\\Bullets.tex",
// ********* ROCKETS *********
20 model MODEL_ROCKETS "Models\\Items\\Ammo\\Rockets\\Rockets.mdl",
21 model MODEL_RC_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl",
22 texture TEXTURE_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex",
// ********* GRENADES *********
30 model MODEL_GRENADES "Models\\Items\\Ammo\\Grenades\\Grenades.mdl",
31 model MODEL_GR_GRENADE "Models\\Items\\Ammo\\Grenades\\Grenade.mdl",
32 texture TEXTURE_GRENADES "Models\\Items\\Ammo\\Grenades\\Grenades.tex",
33 texture TEXTURE_GR_GRENADE "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.tex",
// ********* ELECTRICITY *********
40 model MODEL_ELECTRICITY "Models\\Items\\Ammo\\Electricity\\Electricity.mdl",
41 model MODEL_EL_EFFECT "Models\\Items\\Ammo\\Electricity\\Effect.mdl",
42 model MODEL_EL_EFFECT2 "Models\\Items\\Ammo\\Electricity\\Effect2.mdl",
43 texture TEXTURE_ELECTRICITY "Models\\Items\\Ammo\\Electricity\\Electricity.tex",
44 texture TEXTURE_EL_EFFECT "Models\\Items\\Ammo\\Electricity\\Effect.tex",
// ********* CANNON BALLS *********
50 model MODEL_CANNONBALL "Models\\Items\\Ammo\\Cannonball\\Cannonball.mdl",
51 model MODEL_CANNONBALLS "Models\\Items\\Ammo\\Cannonball\\CannonballQuad.mdl",
52 texture TEXTURE_IRONBALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex",
// 53 texture TEXTURE_NUKEBALL "Models\\Weapons\\Cannon\\Projectile\\NukeBall.tex",
// ********* BACK PACK *********
60 model MODEL_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl",
61 texture TEXTURE_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.tex",
// ********* SERIOUS PACK *********
70 model MODEL_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl",
71 texture TEXTURE_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex",
/*
// ********* FUEL RESERVOIR *********
80 model MODEL_FL_RESERVOIR "Models\\Items\\Ammo\\Napalm\\Napalm.mdl",
81 texture TEXTURE_FL_FUELRESERVOIR "Models\\Weapons\\Flamer\\FuelReservoir.tex",
*/
// ************** FLARE FOR EFFECT **************
100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
// ************** REFLECTIONS **************
200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex",
201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex",
202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex",
204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex",
205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex",
// ************** SPECULAR **************
210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex",
211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex",
// ************** SOUNDS **************
213 sound SOUND_PICK "Sounds\\Items\\Ammo.wav",
214 sound SOUND_DEFAULT "Sounds\\Default.wav",
functions:
void Precache(void) {
PrecacheSound(SOUND_PICK);
}
// render particles
void RenderParticles(void) {
// no particles when not existing or in DM modes
if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE
|| !ShowItemParticles())
{
return;
}
switch (m_EaitType) {
case AIT_SHELLS:
Particles_Spiral(this, 1.0f*0.75, 1.0f*0.75, PT_STAR04, 4);
break;
case AIT_BULLETS:
Particles_Spiral(this, 1.5f*0.75, 1.0f*0.75, PT_STAR04, 6);
break;
case AIT_ROCKETS:
Particles_Spiral(this, 1.5f*0.75, 1.25f*0.75, PT_STAR04, 6);
break;
case AIT_GRENADES:
Particles_Spiral(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 6);
break;
case AIT_ELECTRICITY:
Particles_Spiral(this, 1.5f*0.75, 1.125f*0.75, PT_STAR04, 6);
break;
case AIT_NUKEBALL:
Particles_Spiral(this, 1.25f*0.75, 1.0f*0.75, PT_STAR04, 4);
break;
case AIT_IRONBALLS:
Particles_Spiral(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 8);
break;
case AIT_BACKPACK:
Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10);
break;
case AIT_SERIOUSPACK:
Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10);
break;
case AIT_NAPALM:
Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10);
break;
}
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_ctCount = 1;
pes->es_ctAmmount = m_fValue;
switch (m_EaitType) {
case AIT_SHELLS:
pes->es_strName = "Shells";
pes->es_fValue = m_fValue*AV_SHELLS;
break;
case AIT_BULLETS:
pes->es_strName = "Bullets";
pes->es_fValue = m_fValue*AV_BULLETS;
break;
case AIT_ROCKETS:
pes->es_strName = "Rockets";
pes->es_fValue = m_fValue*AV_ROCKETS;
break;
case AIT_GRENADES:
pes->es_strName = "Grenades";
pes->es_fValue = m_fValue*AV_GRENADES;
break;
case AIT_ELECTRICITY:
pes->es_strName = "Electricity";
pes->es_fValue = m_fValue*AV_ELECTRICITY;
break;
/*
case AIT_NUKEBALL:
pes->es_strName = "Nukeballs";
pes->es_fValue = m_fValue*AV_NUKEBALLS;
break;
*/
case AIT_IRONBALLS:
pes->es_strName = "Ironballs";
pes->es_fValue = m_fValue*AV_IRONBALLS;
break;
case AIT_SERIOUSPACK:
pes->es_strName = "SeriousPack";
pes->es_fValue = m_fValue*100000;
break;
case AIT_BACKPACK:
pes->es_strName = "BackPack";
pes->es_fValue = m_fValue*100000;
break;
/*
case AIT_NAPALM:
pes->es_strName = "Napalm";
pes->es_fValue = m_fValue*AV_NAPALM;
break;
*/
}
pes->es_iScore = 0;//m_iScore;
return TRUE;
}
// set ammo properties depending on ammo type
void SetProperties(void) {
switch (m_EaitType) {
case AIT_SHELLS:
m_fValue = 10.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Shells: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_SHELLS, TEXTURE_SHELLS, 0, 0, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.25f,0), FLOAT3D(1.5,1.5,0.75f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
case AIT_BULLETS:
m_fValue = 50.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Bullets: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_BULLETS, TEXTURE_BULLETS, 0, 0, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(3,3,1.0f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
case AIT_ROCKETS:
m_fValue = 5.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Rockets: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_ROCKETS, TEXTURE_ROCKET, 0, 0, 0);
AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET1, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0);
AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET2, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0);
AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET3, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0);
AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET4, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0);
AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET5, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0);
SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET1, ROCKET_ANIM_FORAMMO);
SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET2, ROCKET_ANIM_FORAMMO);
SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET3, ROCKET_ANIM_FORAMMO);
SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET4, ROCKET_ANIM_FORAMMO);
SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET5, ROCKET_ANIM_FORAMMO);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2,2,0.75f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
case AIT_GRENADES:
m_fValue = 5.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Grenades: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_GRENADES, TEXTURE_GRENADES, 0, 0, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(4,4,1.0f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
case AIT_ELECTRICITY:
m_fValue = 50.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Electricity: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_ELECTRICITY, TEXTURE_ELECTRICITY, TEXTURE_EL_EFFECT, TEXTURE_EL_EFFECT, 0);
AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT1, MODEL_EL_EFFECT, TEXTURE_EL_EFFECT, 0, 0, 0);
AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT2, MODEL_EL_EFFECT, TEXTURE_EL_EFFECT, 0, 0, 0);
AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT3, MODEL_EL_EFFECT2,TEXTURE_EL_EFFECT, 0, 0, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(3,3,0.8f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
/*
case AIT_NUKEBALL:
m_fValue = 1.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Nuke ball: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_CANNONBALL, TEXTURE_NUKEBALL, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(2,2,0.5f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
*/
case AIT_IRONBALLS:
m_fValue = 4.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Iron balls: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_CANNONBALLS, TEXTURE_IRONBALL, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(5,5,1.3f) );
StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f));
break;
/*
case AIT_NAPALM:
m_fValue = 100.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("Napalm: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_FL_RESERVOIR, TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3,3,1.0f) );
StretchItem(FLOAT3D(1.25f, 1.25f, 1.25f));
break;
*/
case AIT_SERIOUSPACK:
m_fValue = 1.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("SeriousPack: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_SERIOUSPACK, TEXTURE_SERIOUSPACK, 0,0,0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) );
StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f));
break;
case AIT_BACKPACK:
m_fValue = 1.0f;
m_fRespawnTime = 30.0f;
m_strDescription.PrintF("BackPack: %d", (int) m_fValue);
// set appearance
AddItem(MODEL_BACKPACK, TEXTURE_BACKPACK, 0,0,0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) );
StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f));
break;
default: ASSERTALWAYS("Uknown ammo");
}
};
void AdjustDifficulty(void)
{
m_fValue = ceil(m_fValue*GetSP()->sp_fAmmoQuantity);
if (GetSP()->sp_bInfiniteAmmo && m_penTarget==NULL) {
Destroy();
}
}
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected {
ASSERT(epass.penOther!=NULL);
// if ammo stays
if (GetSP()->sp_bAmmoStays && !m_bPickupOnce) {
// if already picked by this player
BOOL bWasPicked = MarkPickedBy(epass.penOther);
if (bWasPicked) {
// don't pick again
return;
}
}
// send ammo to entity
EAmmoItem eAmmo;
eAmmo.EaitType = m_EaitType;
eAmmo.iQuantity = (INDEX) m_fValue;
// if health is received
if (epass.penOther->ReceiveItem(eAmmo)) {
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
if(_pNetwork->IsPlayerLocal(epass.penOther)) {IFeel_PlayEffect("PU_Ammo");}
if( (m_EaitType == AIT_SERIOUSPACK) || (m_EaitType == AIT_BACKPACK) )
{
PlaySound(m_soPick, SOUND_DEFAULT, SOF_3D);
CPrintF("^cFF0000^f5Warning!!! Replace old serious pack with new, BackPack entity!^r\n");
}
else
{
PlaySound(m_soPick, SOUND_PICK, SOF_3D);
}
m_fPickSoundLen = GetSoundLength(SOUND_PICK);
if (!GetSP()->sp_bAmmoStays || m_bPickupOnce) {
jump CItem::ItemReceived();
}
}
return;
};
Main() {
if (m_EaitType==AIT_NUKEBALL||
m_EaitType==AIT_NAPALM) {
m_EaitType=AIT_SHELLS;
}
Initialize(); // initialize base class
StartModelAnim(ITEMHOLDER_ANIM_MEDIUMOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

View File

@ -0,0 +1,203 @@
806
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
uses "Entities/Item";
// ammo type
enum AmmoPackType {
1 APT_CUSTOM "Custom pack",
2 APT_SERIOUS "Serious pack",
};
// event for sending through receive item
event EAmmoPackItem {
INDEX iShells,
INDEX iBullets,
INDEX iRockets,
INDEX iGrenades,
// INDEX iNapalm,
INDEX iElectricity,
INDEX iIronBalls,
// INDEX iNukeBalls,
};
class CAmmoPack : CItem {
name "Ammo Pack";
thumbnail "Thumbnails\\AmmoPack.tbn";
properties:
1 enum AmmoPackType m_aptPackType "Type" 'Y' = APT_CUSTOM, // pack type
10 INDEX m_iShells "Shells" 'S' = MAX_SHELLS,
11 INDEX m_iBullets "Bullets" 'B' = MAX_BULLETS,
12 INDEX m_iRockets "Rockets" 'C' = MAX_ROCKETS,
13 INDEX m_iGrenades "Grenades" 'G' = MAX_GRENADES,
// 14 INDEX m_iNapalm "Napalm" 'P' = MAX_NAPALM,
15 INDEX m_iElectricity "Electricity" 'E' = MAX_ELECTRICITY,
16 INDEX m_iIronBalls "Iron balls" 'I' = MAX_IRONBALLS,
// 17 INDEX m_iNukeBalls "Nuke balls" 'U' = MAX_NUKEBALLS,
components:
0 class CLASS_BASE "Classes\\Item.ecl",
// ********* BACK PACK *********
60 model MODEL_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl",
61 texture TEXTURE_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.tex",
// ********* SERIOUS PACK *********
70 model MODEL_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl",
71 texture TEXTURE_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex",
// ************** FLARE FOR EFFECT **************
100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
// ************** SOUNDS **************
213 sound SOUND_PICK "Sounds\\Items\\Ammo.wav",
functions:
void Precache(void) {
PrecacheSound(SOUND_PICK);
}
// render particles
void RenderParticles(void)
{
// no particles when not existing or in DM modes
if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE
|| !ShowItemParticles())
{
return;
}
Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10);
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_ctCount = 1;
pes->es_ctAmmount = 1;
// compile description
// pes->es_strName.PrintF("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Napalm, %d Electricity, %d Iron balls, %d Nuke balls",
// m_iShells, m_iBullets, m_iRockets, m_iGrenades, m_iNapalm, m_iElectricity, m_iIronBalls, m_iNukeBalls);
pes->es_strName.PrintF("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Electricity, %d Iron balls",
m_iShells, m_iBullets, m_iRockets, m_iGrenades, m_iElectricity, m_iIronBalls);
// calculate value
pes->es_fValue =
m_iShells*AV_SHELLS +
m_iBullets*AV_BULLETS +
m_iRockets*AV_ROCKETS +
m_iGrenades*AV_GRENADES +
// m_iNapalm*AV_NAPALM +
m_iElectricity*AV_ELECTRICITY +
m_iIronBalls*AV_IRONBALLS /*+
m_iNukeBalls*AV_NUKEBALLS*/;
pes->es_iScore = 0;
return TRUE;
}
// set ammo properties depending on ammo type
void SetProperties(void)
{
switch (m_aptPackType)
{
case APT_SERIOUS:
m_strDescription = "Serious:";
// set appearance
AddItem(MODEL_SERIOUSPACK, TEXTURE_SERIOUSPACK, 0,0,0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) );
StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f));
break;
case APT_CUSTOM:
m_strDescription = "Custom:";
// set appearance
AddItem(MODEL_BACKPACK, TEXTURE_BACKPACK, 0,0,0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) );
StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f));
break;
default: ASSERTALWAYS("Uknown ammo");
}
m_fValue = 1.0f;
m_fRespawnTime = 30.0f;
if( m_iShells != 0) {m_strDescription.PrintF("%s: Shells (%d)", (const char *) m_strDescription, m_iShells);}
if( m_iBullets != 0) {m_strDescription.PrintF("%s: Bullets (%d)", (const char *) m_strDescription, m_iBullets);}
if( m_iRockets != 0) {m_strDescription.PrintF("%s: Rockets (%d)", (const char *) m_strDescription, m_iRockets);}
if( m_iGrenades != 0) {m_strDescription.PrintF("%s: Grenades (%d)", (const char *) m_strDescription, m_iGrenades);}
// if( m_iNapalm != 0) {m_strDescription.PrintF("%s: Napalm (%d)", (const char *) m_strDescription, m_iNapalm);}
if( m_iElectricity != 0) {m_strDescription.PrintF("%s: Electricity (%d)", (const char *) m_strDescription, m_iElectricity);}
if( m_iIronBalls != 0) {m_strDescription.PrintF("%s: Iron balls (%d)", (const char *) m_strDescription, m_iIronBalls);}
// if( m_iNukeBalls != 0) {m_strDescription.PrintF("%s: Nuke balls (%d)", (const char *) m_strDescription, m_iNukeBalls);}
}
void AdjustDifficulty(void)
{
//m_fValue = ceil(m_fValue*GetSP()->sp_fAmmoQuantity);
if (GetSP()->sp_bInfiniteAmmo && m_penTarget==NULL) {
Destroy();
}
}
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected
{
ASSERT(epass.penOther!=NULL);
// if ammo stays
if (GetSP()->sp_bAmmoStays && !m_bPickupOnce) {
// if already picked by this player
BOOL bWasPicked = MarkPickedBy(epass.penOther);
if (bWasPicked) {
// don't pick again
return;
}
}
// send ammo to entity
EAmmoPackItem eAmmo;
eAmmo.iShells = m_iShells;
eAmmo.iBullets = m_iBullets;
eAmmo.iRockets = m_iRockets;
eAmmo.iGrenades = m_iGrenades;
// eAmmo.iNapalm = m_iNapalm;
eAmmo.iElectricity = m_iElectricity;
eAmmo.iIronBalls = m_iIronBalls;
// eAmmo.iNukeBalls = m_iNukeBalls;
// if health is received
if (epass.penOther->ReceiveItem(eAmmo)) {
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soPick, SOUND_PICK, SOF_3D);
m_fPickSoundLen = GetSoundLength(SOUND_PICK);
if (!GetSP()->sp_bAmmoStays || m_bPickupOnce) {
jump CItem::ItemReceived();
}
}
return;
};
Main() {
m_iShells = Clamp( m_iShells, INDEX(0), MAX_SHELLS);
m_iBullets = Clamp( m_iBullets, INDEX(0), MAX_BULLETS);
m_iRockets = Clamp( m_iRockets, INDEX(0), MAX_ROCKETS);
m_iGrenades = Clamp( m_iGrenades, INDEX(0), MAX_GRENADES);
// m_iNapalm = Clamp( m_iNapalm, INDEX(0), MAX_NAPALM);
m_iElectricity = Clamp( m_iElectricity, INDEX(0), MAX_ELECTRICITY);
m_iIronBalls = Clamp( m_iIronBalls, INDEX(0), MAX_IRONBALLS);
// m_iNukeBalls = Clamp( m_iNukeBalls, INDEX(0), MAX_NUKEBALLS);
Initialize(); // initialize base class
StartModelAnim(ITEMHOLDER_ANIM_MEDIUMOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

View File

@ -0,0 +1,146 @@
218
%{
#include "Entities/StdH/StdH.h"
#include <Entities/AnimationHub.h>
%}
uses "Entities/ModelHolder2";
uses "Entities/Light";
// event sent to the entity that should change animation
event EChangeAnim {
INDEX iModelAnim,
BOOL bModelLoop,
INDEX iTextureAnim,
BOOL bTextureLoop,
INDEX iLightAnim,
INDEX iAmbientLightAnim,
BOOL bLightLoop,
BOOL bAmbientLightLoop,
COLOR colAmbient,
COLOR colDiffuse,
};
class CAnimationChanger : CRationalEntity {
name "AnimationChanger";
thumbnail "Thumbnails\\AnimationChanger.tbn";
features "HasName", "HasTarget", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Animation changer",
2 CTString m_strDescription = "",
3 CEntityPointer m_penTarget "Target" 'T' COLOR(C_GREEN|0xFF),
4 ANIMATION m_iModelAnim "Model Animation" 'M' = 0,
5 BOOL m_bModelLoop "Model Looping" = FALSE,
6 ANIMATION m_iTextureAnim "Texture Animation" 'X' = 0,
7 BOOL m_bTextureLoop "Texture Looping" = FALSE,
8 ANIMATION m_iLightAnim "Diffuse Light Animation" 'L' = 0,
9 BOOL m_bLightLoop "Diffuse Light Looping" = FALSE,
10 ANIMATION m_iAmbientLightAnim "Ambient Light Animation" 'B' = 0,
11 BOOL m_bAmbientLightLoop "Ambient Light Looping" = FALSE,
12 COLOR m_colAmbient "Ambient Light Color" 'A' = C_dBLUE,
13 COLOR m_colDiffuse "Diffuse Light Color" 'C' = C_GRAY,
components:
1 model MODEL_CHANGER "Models\\Editor\\AnimationChanger.mdl",
2 texture TEXTURE_CHANGER "Models\\Editor\\AnimationChanger.tex"
functions:
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",(const char *) m_penTarget->GetName());
}
return m_strDescription;
}
/* Get anim data for given animation property - return NULL for none. */
CAnimData *GetAnimData(SLONG slPropertyOffset)
{
CEntity *penTarget = m_penTarget;
if (penTarget==NULL) {
return NULL;
}
if (IsOfClass(penTarget, "AnimationHub")) {
penTarget = ((CAnimationHub*)penTarget)->m_penTarget0;
}
if (penTarget==NULL) {
return NULL;
}
// if modelholder
if (IsOfClass(penTarget, "ModelHolder2")) {
CModelHolder2 *penModel = (CModelHolder2*)&*penTarget;
if (slPropertyOffset==offsetof(CAnimationChanger, m_iModelAnim)) {
return penModel->GetModelObject()->GetData();
} else if (slPropertyOffset==offsetof(CAnimationChanger, m_iTextureAnim)) {
return penModel->GetModelObject()->mo_toTexture.GetData();
} else if (slPropertyOffset==offsetof(CAnimationChanger, m_iLightAnim)) {
return penModel->m_aoLightAnimation.GetData();
}
// if light
} else if (IsOfClass(penTarget, "Light")) {
CLight *penLight = (CLight*)&*penTarget;
if (slPropertyOffset==offsetof(CAnimationChanger, m_iLightAnim))
{
return penLight->m_aoLightAnimation.GetData();
}
else if (slPropertyOffset==offsetof(CAnimationChanger, m_iAmbientLightAnim))
{
return penLight->m_aoAmbientLightAnimation.GetData();
}
}
return CEntity::GetAnimData(slPropertyOffset);
};
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_CHANGER);
SetModelMainTexture(TEXTURE_CHANGER);
// check target type
if (m_penTarget!=NULL &&
!IsOfClass(m_penTarget, "AnimationHub") &&
!IsOfClass(m_penTarget, "ModelHolder2") &&
!IsOfClass(m_penTarget, "Light")) {
WarningMessage("Target must be AnimationHub ModelHolder2 or Light!");
m_penTarget=NULL;
}
if (m_penTarget==NULL) {
return;
}
//main loop
wait() {
on (EBegin) : { resume; }
on (EStart) : {
EChangeAnim eChange;
eChange.iModelAnim =m_iModelAnim ;
eChange.iTextureAnim =m_iTextureAnim;
eChange.iLightAnim =m_iLightAnim ;
eChange.iAmbientLightAnim =m_iAmbientLightAnim;
eChange.bModelLoop =m_bModelLoop ;
eChange.bTextureLoop =m_bTextureLoop;
eChange.bLightLoop =m_bLightLoop ;
eChange.colAmbient =m_colAmbient ;
eChange.colDiffuse =m_colDiffuse ;
m_penTarget->SendEvent(eChange);
resume;
}
}
return;
}
};

View File

@ -0,0 +1,147 @@
228
%{
#include "Entities/StdH/StdH.h"
#include <Entities/AnimationChanger.h>
%}
class CAnimationHub : CRationalEntity {
name "AnimationHub";
thumbnail "Thumbnails\\AnimationHub.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Animation hub",
2 CTString m_strDescription = "",
3 FLOAT m_tmDelayEach "Delay each" 'D' = 0.0f,
10 CEntityPointer m_penTarget0 "Target0" 'T' COLOR(C_GREEN|0xFF),
11 CEntityPointer m_penTarget1 "Target1" COLOR(C_GREEN|0xFF),
12 CEntityPointer m_penTarget2 "Target2" COLOR(C_GREEN|0xFF),
13 CEntityPointer m_penTarget3 "Target3" COLOR(C_GREEN|0xFF),
14 CEntityPointer m_penTarget4 "Target4" COLOR(C_GREEN|0xFF),
15 CEntityPointer m_penTarget5 "Target5" COLOR(C_GREEN|0xFF),
16 CEntityPointer m_penTarget6 "Target6" COLOR(C_GREEN|0xFF),
17 CEntityPointer m_penTarget7 "Target7" COLOR(C_GREEN|0xFF),
18 CEntityPointer m_penTarget8 "Target8" COLOR(C_GREEN|0xFF),
19 CEntityPointer m_penTarget9 "Target9" COLOR(C_GREEN|0xFF),
20 FLOAT m_tmDelay0 "Delay0" = 0.0f,
21 FLOAT m_tmDelay1 "Delay1" = 0.0f,
22 FLOAT m_tmDelay2 "Delay2" = 0.0f,
23 FLOAT m_tmDelay3 "Delay3" = 0.0f,
24 FLOAT m_tmDelay4 "Delay4" = 0.0f,
25 FLOAT m_tmDelay5 "Delay5" = 0.0f,
26 FLOAT m_tmDelay6 "Delay6" = 0.0f,
27 FLOAT m_tmDelay7 "Delay7" = 0.0f,
28 FLOAT m_tmDelay8 "Delay8" = 0.0f,
29 FLOAT m_tmDelay9 "Delay9" = 0.0f,
100 INDEX m_iModelAnim = 0,
101 BOOL m_bModelLoop = 0,
102 INDEX m_iTextureAnim = 0,
103 BOOL m_bTextureLoop = 0,
104 INDEX m_iLightAnim = 0,
105 BOOL m_bLightLoop = 0,
106 COLOR m_colAmbient = 0,
107 COLOR m_colDiffuse = 0,
110 INDEX m_iCounter = 0,
components:
1 model MODEL_HUB "Models\\Editor\\AnimationHub.mdl",
2 texture TEXTURE_HUB "Models\\Editor\\AnimationHub.tex"
functions:
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget0!=NULL) {
((CTString&)m_strDescription).PrintF("->%s...",(const char *) m_penTarget0->GetName());
}
return m_strDescription;
}
procedures:
RelayEvents()
{
// for each target
m_iCounter=0;
while(m_iCounter<10) {
// get delay
FLOAT fDelay = m_tmDelayEach + (&m_tmDelay0)[m_iCounter];
// if has delay
if (fDelay>0) {
// wait
autowait(fDelay);
}
// get the target
CEntity *penTarget = (&m_penTarget0)[m_iCounter];
// if no more targets
if (penTarget==NULL) {
// stop
jump WaitChange();
}
// sent event to it
EChangeAnim eca;
eca.iModelAnim = m_iModelAnim ;
eca.bModelLoop = m_bModelLoop ;
eca.iTextureAnim = m_iTextureAnim;
eca.bTextureLoop = m_bTextureLoop;
eca.iLightAnim = m_iLightAnim ;
eca.bLightLoop = m_bLightLoop ;
eca.colAmbient = m_colAmbient ;
eca.colDiffuse = m_colDiffuse ;
penTarget->SendEvent(eca);
m_iCounter++;
}
jump WaitChange();
}
WaitChange()
{
// wait forever
while(TRUE) {
wait() {
on (EChangeAnim eca) : {
m_iModelAnim = eca.iModelAnim ;
m_bModelLoop = eca.bModelLoop ;
m_iTextureAnim = eca.iTextureAnim;
m_bTextureLoop = eca.bTextureLoop;
m_iLightAnim = eca.iLightAnim ;
m_bLightLoop = eca.bLightLoop ;
m_colAmbient = eca.colAmbient ;
m_colDiffuse = eca.colDiffuse ;
jump RelayEvents();
}
}
}
}
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_HUB);
SetModelMainTexture(TEXTURE_HUB);
// check target types
for (INDEX i=0; i<10; i++) {
CEntityPointer &penTarget = (&m_penTarget0)[i];
if (penTarget!=NULL &&
!IsOfClass(penTarget, "ModelHolder2") &&
!IsOfClass(penTarget, "Light")) {
WarningMessage("All targets must be ModelHolder2 or Light!");
penTarget=NULL;
}
}
jump WaitChange();
}
};

View File

@ -0,0 +1,254 @@
804
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
uses "Entities/Item";
// health type
enum ArmorItemType {
0 ARIT_SHARD "Shard", // shard
1 ARIT_SMALL "Small", // small armor
2 ARIT_MEDIUM "Medium", // medium armor
3 ARIT_STRONG "Strong", // strong armor
4 ARIT_SUPER "Super", // super armor
};
// event for sending through receive item
event EArmor {
FLOAT fArmor, // armor to receive
BOOL bOverTopArmor, // can be received over top armor
};
class CArmorItem : CItem {
name "Armor Item";
thumbnail "Thumbnails\\ArmorItem.tbn";
properties:
1 enum ArmorItemType m_EaitType "Type" 'Y' = ARIT_SHARD, // armor type
2 BOOL m_bOverTopArmor = FALSE, // can be received over top armor
3 INDEX m_iSoundComponent = 0,
components:
0 class CLASS_BASE "Classes\\Item.ecl",
// ********* SHARD *********
1 model MODEL_1 "Models\\Items\\Armor\\Armor_1.mdl",
2 texture TEXTURE_1 "Models\\Items\\Armor\\Armor_1.tex",
// ********* SMALL ARMOR *********
10 model MODEL_25 "Models\\Items\\Armor\\Armor_25.mdl",
11 texture TEXTURE_25 "Models\\Items\\Armor\\Armor_25.tex",
// ********* MEDIUM ARMOR *********
20 model MODEL_50 "Models\\Items\\Armor\\Armor_50.mdl",
21 texture TEXTURE_50 "Models\\Items\\Armor\\Armor_50.tex",
// ********* STRONG ARMOR *********
22 model MODEL_100 "Models\\Items\\Armor\\Armor_100.mdl",
23 texture TEXTURE_100 "Models\\Items\\Armor\\Armor_100.tex",
// ********* SUPER ARMOR *********
40 model MODEL_200 "Models\\Items\\Armor\\Armor_200.mdl",
41 texture TEXTURE_200 "Models\\Items\\Armor\\Armor_200.tex",
// ************** FLARE FOR EFFECT **************
100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
// ************** REFLECTIONS **************
200 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
// ************** SPECULAR **************
210 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
// ************** SOUNDS **************
301 sound SOUND_SHARD "Sounds\\Items\\ArmourShard.wav",
302 sound SOUND_SMALL "Sounds\\Items\\ArmourSmall.wav",
303 sound SOUND_MEDIUM "Sounds\\Items\\ArmourMedium.wav",
304 sound SOUND_STRONG "Sounds\\Items\\ArmourStrong.wav",
305 sound SOUND_SUPER "Sounds\\Items\\ArmourSuper.wav",
functions:
void Precache(void) {
switch (m_EaitType) {
case ARIT_SHARD: PrecacheSound(SOUND_SHARD ); break;
case ARIT_SMALL: PrecacheSound(SOUND_SMALL ); break;
case ARIT_MEDIUM: PrecacheSound(SOUND_MEDIUM); break;
case ARIT_STRONG: PrecacheSound(SOUND_STRONG); break;
case ARIT_SUPER: PrecacheSound(SOUND_SUPER ); break;
}
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_strName = "Armor";
pes->es_ctCount = 1;
pes->es_ctAmmount = m_fValue;
pes->es_fValue = m_fValue*2;
pes->es_iScore = 0;//m_iScore;
switch (m_EaitType) {
case ARIT_SHARD: pes->es_strName+=" shard"; break;
case ARIT_SMALL: pes->es_strName+=" small";break;
case ARIT_MEDIUM: pes->es_strName+=" medium";break;
case ARIT_STRONG: pes->es_strName+=" strong";break;
case ARIT_SUPER: pes->es_strName+=" super";break;
}
return TRUE;
}
// render particles
void RenderParticles(void) {
// no particles when not existing or in DM modes
if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE
|| !ShowItemParticles())
{
return;
}
switch (m_EaitType) {
case ARIT_SHARD:
Particles_Emanate(this, 0.75f*0.75, 0.75f*0.75, PT_STAR04, 8);
break;
case ARIT_SMALL:
Particles_Emanate(this, 1.0f*0.75, 1.0f*0.75, PT_STAR04, 32);
break;
case ARIT_MEDIUM:
Particles_Emanate(this, 1.5f*0.75, 1.5f*0.75, PT_STAR04, 64);
break;
case ARIT_STRONG:
Particles_Emanate(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 96);
break;
case ARIT_SUPER:
Particles_Emanate(this, 2.5f*0.75, 1.5f*0.75, PT_STAR04, 128);
break;
}
}
// set health properties depending on health type
void SetProperties(void) {
switch (m_EaitType) {
case ARIT_SHARD:
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL);
m_fValue = 1.0f;
m_bOverTopArmor = TRUE;
m_fRespawnTime = 10.0f;
m_strDescription.PrintF("Shard - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_1, TEXTURE_1, 0, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.4f,0), FLOAT3D(1.0,1.0,0.3f) );
StretchItem(FLOAT3D(0.75f*0.75, 0.75f*0.75, 0.75f*0.75));
m_iSoundComponent = SOUND_SHARD;
break;
case ARIT_SMALL:
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 25.0f;
m_bOverTopArmor = FALSE;
m_fRespawnTime = 10.0f;
m_strDescription.PrintF("Small - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_25, TEXTURE_25, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2,2,0.5f) );
StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f));
m_iSoundComponent = SOUND_SMALL;
break;
case ARIT_MEDIUM: {
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 50.0f;
m_bOverTopArmor = FALSE;
m_fRespawnTime = 25.0f;
m_strDescription.PrintF("Medium - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_50, TEXTURE_50, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,1.0f,0), FLOAT3D(3,3,0.5f) );
StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f));
m_iSoundComponent = SOUND_MEDIUM;
} break;
case ARIT_STRONG:
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 100.0f;
m_bOverTopArmor = FALSE;
m_fRespawnTime = 60.0f;
m_strDescription.PrintF("Strong - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_100, TEXTURE_100, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3.5,3.5,1.0f) );
StretchItem(FLOAT3D(2.5f, 2.5f, 2.5f));
m_iSoundComponent = SOUND_STRONG;
break;
case ARIT_SUPER:
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 200.0f;
m_bOverTopArmor = TRUE;
m_fRespawnTime = 120.0f;
m_strDescription.PrintF("Super - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_200, TEXTURE_200, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3,3,1.0f) );
StretchItem(FLOAT3D(2.5f, 2.5f, 2.5f));
m_iSoundComponent = SOUND_SUPER;
break;
}
};
void AdjustDifficulty(void)
{
if (!GetSP()->sp_bAllowArmor && m_penTarget==NULL) {
Destroy();
}
}
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected {
ASSERT(epass.penOther!=NULL);
// if armor stays
if (GetSP()->sp_bHealthArmorStays && !m_bPickupOnce) {
// if already picked by this player
BOOL bWasPicked = MarkPickedBy(epass.penOther);
if (bWasPicked) {
// don't pick again
return;
}
}
// send health to entity
EArmor eArmor;
eArmor.fArmor = m_fValue;
eArmor.bOverTopArmor = m_bOverTopArmor;
// if health is received
if (epass.penOther->ReceiveItem(eArmor)) {
if(_pNetwork->IsPlayerLocal(epass.penOther))
{
switch (m_EaitType)
{
case ARIT_SHARD: IFeel_PlayEffect("PU_ArmourShard"); break;
case ARIT_SMALL: IFeel_PlayEffect("PU_ArmourSmall"); break;
case ARIT_MEDIUM: IFeel_PlayEffect("PU_ArmourMedium"); break;
case ARIT_STRONG: IFeel_PlayEffect("PU_ArmourStrong"); break;
case ARIT_SUPER: IFeel_PlayEffect("PU_ArmourSuper"); break;
}
}
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soPick, m_iSoundComponent, SOF_3D);
m_fPickSoundLen = GetSoundLength(m_iSoundComponent);
if (!GetSP()->sp_bHealthArmorStays || m_bPickupOnce) {
jump CItem::ItemReceived();
}
}
return;
};
Main() {
Initialize(); // initialize base class
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

View File

@ -0,0 +1,68 @@
211
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
class CBackgroundViewer: CMarker {
name "Background Viewer";
thumbnail "Thumbnails\\BackgroundViewer.tbn";
features "IsImportant";
properties:
1 BOOL m_bActive "Active" 'A' =TRUE, // set if active at beginning of game
2 CEntityPointer m_penWorldSettingsController "World settings controller" 'W',
components:
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex"
functions:
// Validate offered target for one property
BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget)
{
if(penTarget==NULL)
{
return FALSE;
}
// if gradient marker
if( slPropertyOffset==offsetof(CBackgroundViewer, m_penWorldSettingsController))
{
return IsOfClass(penTarget, "WorldSettingsController");
}
return TRUE;
}
BOOL HandleEvent(const CEntityEvent &ee) {
if (ee.ee_slEvent == EVENTCODE_EStart) {
GetWorld()->SetBackgroundViewer(this);
return TRUE;
}
return FALSE;
};
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if (m_strName=="Marker") {
m_strName = "Background Viewer";
}
if (m_bActive) {
GetWorld()->SetBackgroundViewer(this);
}
return;
}
};

File diff suppressed because it is too large Load Diff

450
Sources/Entities/Beast.es Normal file
View File

@ -0,0 +1,450 @@
336
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Beast/Beast.h"
#include "Entities/WorldSettingsController.h"
#include "Entities/BackgroundViewer.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
enum BeastType {
0 BT_NORMAL "Small", // normal (fighter)
1 BT_BIG "Big", // big
};
%{
static int _tmLastStandingAnim =0;
#define BEAST_STRETCH 2.0f
#define BIG_BEAST_STRETCH 12.0f
// info structure
static EntityInfo eiBeastNormal = {
EIBT_FLESH, 1500.0f,
0.0f, 2.0f*BEAST_STRETCH, 0.0f, // source (eyes)
0.0f, 1.5f*BEAST_STRETCH, 0.0f, // target (body)
};
static EntityInfo eiBeastBig = {
EIBT_FLESH, 5000.0f,
0.0f, 2.0f*BIG_BEAST_STRETCH, 0.0f, // source (eyes)
0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f, // target (body)
};
%}
class CBeast : CEnemyBase {
name "Beast";
thumbnail "Thumbnails\\Beast.tbn";
properties:
1 enum BeastType m_bcType "Character" 'C' = BT_NORMAL,
2 INDEX m_iCounter = 0,
3 BOOL m_bBeBoss "Boss" 'B' = FALSE,
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
10 model MODEL_BEAST "Models\\Enemies\\Beast\\Beast.mdl",
11 texture TEXTURE_BEAST_NORMAL "Models\\Enemies\\Beast\\Beast.tex",
12 texture TEXTURE_BEAST_BIG "Models\\Enemies\\Beast\\BeastBig.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Beast\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Beast\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Beast\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Beast\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Beast\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Beast\\Sounds\\Death.wav",
56 sound SOUND_DEATHBIG "Models\\Enemies\\Beast\\Sounds\\DeathBig.wav",
57 sound SOUND_ANGER "Models\\Enemies\\Beast\\Sounds\\Anger.wav",
functions:
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
str.PrintF(TRANS("A Reptiloid killed %s"),(const char*) strPlayerName);
return str;
}
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnmNormal, "Data\\Messages\\Enemies\\BeastNormal.txt");
static DECLARE_CTFILENAME(fnmBig, "Data\\Messages\\Enemies\\BeastBig.txt");
switch(m_bcType) {
default: ASSERT(FALSE);
case BT_NORMAL: return fnmNormal;
case BT_BIG: return fnmBig;
}
};
void Precache(void) {
CEnemyBase::Precache();
PrecacheSound(SOUND_IDLE );
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_ANGER);
PrecacheSound(SOUND_FIRE);
PrecacheSound(SOUND_KICK);
PrecacheModel(MODEL_BEAST);
PrecacheTexture(TEXTURE_BEAST_NORMAL);
PrecacheTexture(TEXTURE_BEAST_BIG);
if (m_bcType == BT_NORMAL) {
PrecacheSound(SOUND_DEATH);
PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_PROJECTILE);
} else {
PrecacheSound(SOUND_DEATHBIG);
PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_BIG_PROJECTILE);
}
};
/* Entity info */
void *GetEntityInfo(void) {
if (m_bcType == BT_NORMAL) {
return &eiBeastNormal;
} else {
return &eiBeastBig;
}
};
class CWorldSettingsController *GetWSC(void)
{
CWorldSettingsController *pwsc = NULL;
// obtain bcg viewer
CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer();
if( penBcgViewer != NULL) {
// obtain world settings controller
pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController;
}
return pwsc;
}
void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower)
{
CWorldSettingsController *pwsc = GetWSC();
if (pwsc!=NULL) {
pwsc->m_tmShakeStarted = tmShaketime;
pwsc->m_vShakePos = GetPlacement().pl_PositionVector;
pwsc->m_fShakeFalloff = 400.0f;
pwsc->m_fShakeFade = 3.0f;
pwsc->m_fShakeIntensityZ = 0.0f;
pwsc->m_tmShakeFrequencyZ = 5.0f;
pwsc->m_fShakeIntensityY = 0.1f*fPower;
pwsc->m_tmShakeFrequencyY = 5.0f;
pwsc->m_fShakeIntensityB = 2.5f*fPower;
pwsc->m_tmShakeFrequencyB = 7.2f;
}
}
FLOAT GetCrushHealth(void)
{
if (m_bcType == BT_BIG) {
return 100.0f;
}
return 0.0f;
}
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// can't harm own class
if (!IsOfClass(penInflictor, "Beast")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
if(m_bcType==BT_BIG && GetHealth() <= m_fMaxHealth/2) {
iAnim = BEAST_ANIM_ANGER;
} else {
iAnim = BEAST_ANIM_WOUND;
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
if(m_bcType==BT_BIG) {
iAnim = BEAST_ANIM_DEATHBIG;
} else {
iAnim = BEAST_ANIM_DEATH;
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(BEAST_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
_tmLastStandingAnim = _pTimer->CurrentTick();
StartModelAnim(BEAST_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void) {
if(_pTimer->CurrentTick()>=_tmLastStandingAnim-_pTimer->TickQuantum &&
_pTimer->CurrentTick()<=_tmLastStandingAnim+_pTimer->TickQuantum)
{
BREAKPOINT;
}
if(m_bcType==BT_BIG) {
StartModelAnim(BEAST_ANIM_WALKBIG, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(BEAST_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
}
};
void RunningAnim(void) {
WalkingAnim();
};
void RotatingAnim(void) {
WalkingAnim();
};
// 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) {
if(m_bcType==BT_BIG && GetHealth() <= m_fMaxHealth/2) {
PlaySound(m_soSound, SOUND_ANGER, SOF_3D);
} else {
PlaySound(m_soSound, SOUND_WOUND, SOF_3D);
}
};
void DeathSound(void) {
if (m_bcType == BT_NORMAL) {
PlaySound(m_soSound, SOUND_DEATH, SOF_3D);
} else {
PlaySound(m_soSound, SOUND_DEATHBIG, SOF_3D);
}
};
// adjust sound and watcher parameters here if needed
void EnemyPostInit(void)
{
m_soSound.Set3DParameters(160.0f, 50.0f, 2.0f, 1.0f);
};
procedures:
/************************************************************
* D E A T H *
************************************************************/
Death(EVoid) : CEnemyBase::Death {
if (m_bcType == BT_NORMAL) {
jump CEnemyBase::Death();
}
// stop moving
StopMoving();
DeathSound(); // death sound
LeaveStain(TRUE);
// set physic flags
SetPhysicsFlags(EPF_MODEL_CORPSE);
SetCollisionFlags(ECF_CORPSE);
SetFlags(GetFlags() | ENF_SEETHROUGH);
// stop making fuss
RemoveFromFuss();
// death notify (usually change collision box and change body density)
DeathNotify();
// start death anim
AnimForDeath();
autowait(1.0f);
ShakeItBaby(_pTimer->CurrentTick(), 2.0f);
autowait(2.4f-1.0f);
ShakeItBaby(_pTimer->CurrentTick(), 5.0f);
autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_DEATHBIG)-3.4f);
return EEnd();
};
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
Fire(EVoid) : CEnemyBase::Fire
{
// wait to finish walk and smooth change to idle
StartModelAnim(BEAST_ANIM_WALKTOIDLE, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
if( m_bcType == BT_NORMAL)
{
StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.51f);
ShootProjectile(PRT_BEAST_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BEAST_STRETCH, 0.0f),
ANGLE3D(AngleDeg((FRnd()-0.5)*30.0f), AngleDeg(FRnd()*10.0f), 0));
autowait(0.3f);
}
if( m_bcType == BT_BIG)
{
if( GetHealth() <= m_fMaxHealth/2)
{
m_iCounter = 0;
while ( m_iCounter<6)
{
StartModelAnim(BEAST_ANIM_ATTACKFAST, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.34f);
ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f),
ANGLE3D( AngleDeg(40.0f*Cos(m_iCounter*360.0/6.0f)), AngleDeg(20.0f*Sin(m_iCounter*180.0/6.0f)), 0));
//autowait(0.15f);
m_iCounter++;
}
m_fAttackFireTime = 7.0f;
}
if( GetHealth() > m_fMaxHealth/2)
{
m_iCounter = 0;
while ( m_iCounter<3)
{
StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.5f);
ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f),
ANGLE3D( AngleDeg(20.0f*Cos(m_iCounter*360.0/3.0f)), AngleDeg(10.0f*Sin(m_iCounter*180.0/3.0f)), 0));
//autowait(0.25f);
m_iCounter++;
}
}
}
MaybeSwitchToAnotherPlayer();
autowait(FRnd()/2 + _pTimer->TickQuantum);
if( m_penEnemy != NULL)
{
FLOAT fEnemyDistance = CalcDist(m_penEnemy);
if( fEnemyDistance>m_fCloseDistance*1.25f)
{
StartModelAnim(BEAST_ANIM_IDLETOWALK, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_IDLETOWALK)/2.0f - _pTimer->TickQuantum);
}
}
return EReturn();
};
// hit enemy
Hit(EVoid) : CEnemyBase::Hit {
// close attack
StartModelAnim(BEAST_ANIM_KICK, 0);
autowait(0.45f);
/*
StartModelAnim(BEAST_ANIM_KICK, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
*/
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
if (CalcDist(m_penEnemy) < m_fCloseDistance) {
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
if (m_bcType == BT_BIG) {
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 80.0f, FLOAT3D(0, 0, 0), vDirection);
} else {
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 40.0f, FLOAT3D(0, 0, 0), vDirection);
}
}
/*
StartModelAnim(BEAST_ANIM_IDLE, AOF_SMOOTHCHANGE);
autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn;
*/
autowait(0.45f);
MaybeSwitchToAnotherPlayer();
return EReturn();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
en_fDensity = 1100.0f;
// set your appearance
SetModel(MODEL_BEAST);
StandingAnim();
// setup moving speed
m_fWalkSpeed = FRnd()*2 + 5.0f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 50.0f);
m_fCloseRunSpeed = FRnd() + 10.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 900.0f);
// setup attack distances
m_fAttackDistance = 500.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 0.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 750.0f;
m_bBoss = m_bBeBoss;
m_fStopDistance = 5.0f;
m_fCloseDistance = 7.0f;
m_tmGiveUp = Max(m_tmGiveUp, 10.0f);
// damage/explode properties
if( m_bcType == BT_NORMAL)
{
m_fAttackRunSpeed = 6.0f;//6
m_aAttackRotateSpeed = AngleDeg(3600.0f);
SetHealth(400.0f);
SetModelMainTexture(TEXTURE_BEAST_NORMAL);
m_fBlowUpAmount = 10000.0f;
m_fBodyParts = 4;
m_fDamageWounded = 250.0f;
m_iScore = 5000;//500
// set stretch factor
GetModelObject()->StretchModel(FLOAT3D(BEAST_STRETCH, BEAST_STRETCH, BEAST_STRETCH));
ModelChangeNotify();
m_sptType = SPT_SLIME;
m_fAttackFireTime = 3.0f;
}
else
{
m_fAttackRunSpeed = 8.0f;//8
m_aAttackRotateSpeed = AngleDeg(600.0f);
SetHealth(2000.0f);//500
SetModelMainTexture(TEXTURE_BEAST_BIG);
m_fBlowUpAmount = 10000.0f;//500
m_fBodyParts = 6;
m_fDamageWounded = 650.0f;//500
m_iScore = 25000; //1000
m_fStopDistance = 15;
m_fCloseDistance = 20;
// set stretch factor
GetModelObject()->StretchModel(FLOAT3D(BIG_BEAST_STRETCH, BIG_BEAST_STRETCH, BIG_BEAST_STRETCH));
ModelChangeNotify();
m_sptType = SPT_BLOOD;
m_fAttackFireTime = 5.0f;
}
m_fMaxHealth = GetHealth();
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

209
Sources/Entities/BigHead.es Normal file
View File

@ -0,0 +1,209 @@
340
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Mental/Mental.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
%{
// info structure
static EntityInfo eiMental = {
EIBT_FLESH, 200.0f,
0.0f, 1.5f, 0.0f, // source (eyes)
0.0f, 1.0f, 0.0f, // target (body)
};
#define GREET_SENSE_RANGE 10.0f
#define GREET_SENSE_DELAY 30.0f
%}
class CBigHead: CEnemyBase {
name "BigHead";
thumbnail "Thumbnails\\Mental.tbn";
properties:
// class internal
1 CTFileName m_fnmHeadTex "Head texture" 'H' = CTString(""),
2 CTFileName m_fnmNameSnd "Name sound" 'S' = CTString(""),
3 FLOAT m_tmLastGreetTime = -100.0f,
{
CAutoPrecacheSound m_aps;
CAutoPrecacheTexture m_apt;
}
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl",
3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** DATA **************
10 model MODEL_MENTAL "Models\\Enemies\\Mental\\Mental.mdl",
11 texture TEXTURE_MENTAL "Models\\Enemies\\Mental\\Mental.tex",
12 model MODEL_HEAD "Models\\Enemies\\Mental\\Head.mdl",
50 sound SOUND_IDLE "Models\\Enemies\\Mental\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Mental\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Mental\\Sounds\\Wound.wav",
53 sound SOUND_DEATH "Models\\Enemies\\Mental\\Sounds\\Death.wav",
functions:
/* Entity info */
void *GetEntityInfo(void)
{
return &eiMental;
};
void Precache(void)
{
CEnemyBase::Precache();
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_IDLE);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_DEATH);
m_aps.Precache(m_fnmNameSnd);
m_apt.Precache(m_fnmHeadTex);
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
iAnim = MENTAL_ANIM_PANIC;
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
iAnim = MENTAL_ANIM_DEATH;
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
// ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(MENTAL_ANIM_GROUNDREST, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void) {
StartModelAnim(MENTAL_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
if (_pTimer->CurrentTick()>m_tmLastGreetTime+GREET_SENSE_DELAY) {
m_fSenseRange = GREET_SENSE_RANGE;
m_bDeaf = FALSE;
}
};
void RunningAnim(void)
{
StartModelAnim(MENTAL_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
RunningAnim();
};
// 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);
};
procedures:
Fire(EVoid) : CEnemyBase::Fire {
// hit
if (CalcDist(m_penEnemy) <= m_fStopDistance*1.1f) {
PlaySound(m_soSound, m_fnmNameSnd, SOF_3D);
m_bBlind = TRUE;
m_bDeaf = TRUE;
m_fSenseRange = 0.0f;
m_tmLastGreetTime = _pTimer->CurrentTick();
SetTargetNone();
StartModelAnim(MENTAL_ANIM_GREET, 0);
autowait(GetModelObject()->GetCurrentAnimLength());
StandingAnim();
return EReconsiderBehavior();
}
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);
SetHealth(20.0f);
m_fMaxHealth = 20.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 2000.0f;
m_fBlowUpSize = 2.0f;
// set your appearance
SetModel(MODEL_MENTAL);
SetModelMainTexture(TEXTURE_MENTAL);
AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL);
if (m_fnmHeadTex!="") {
// try to
try {
CAttachmentModelObject *pamoHead = GetModelObject()->GetAttachmentModel(0);
if (pamoHead!=NULL) {
pamoHead->amo_moModelObject.mo_toTexture.SetData_t(m_fnmHeadTex);
}
// if anything failed
} catch (char *strError) {
// report error
CPrintF("%s\n", strError);
AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL);
}
}
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd()*2.0f + 6.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 6.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 5.0f; // greeting distance
m_fAttackFireTime = 0.1f;
m_fCloseFireTime = 0.1f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 65.0f;
m_fBodyParts = 4;
m_fDamageWounded = 1.0f;
m_iScore = 0;
m_bBlind = TRUE;
m_fSenseRange = GREET_SENSE_RANGE;
// set stretch factors for height and width
const FLOAT fSize = 0.6f;
GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize));
ModelChangeNotify();
StandingAnim();
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,126 @@
612
%{
#include "Entities/StdH/StdH.h"
#include "Entities/WorldSettingsController.h"
#include "Entities/BackgroundViewer.h"
%}
uses "Entities/Marker";
enum BlendControllerType {
0 BCT_NONE "None", // no FX
1 BCT_PYRAMID_PLATES "Appear pyramid plates", // effect of appearing of pyramid plates
2 BCT_ACTIVATE_PLATE_1 "Activate plate 1", // plate 1 activating
3 BCT_ACTIVATE_PLATE_2 "Activate plate 2", // plate 2 activating
4 BCT_ACTIVATE_PLATE_3 "Activate plate 3", // plate 3 activating
5 BCT_ACTIVATE_PLATE_4 "Activate plate 4", // plate 4 activating
6 BCT_ACTIVATE_PYRAMID_MORPH_ROOM "Pyramid morph room", // pyramid morph room activated
};
class CBlendController: CMarker
{
name "Blend controller";
thumbnail "Thumbnails\\BlendController.tbn";
features "IsImportant";
properties:
1 enum BlendControllerType m_bctType "Blend type" 'Y' = BCT_NONE, // type of effect
components:
1 model MODEL_CONTROLLER "Models\\Editor\\BlendController.mdl",
2 texture TEXTURE_CONTROLLER "Models\\Editor\\BlendController.tex",
functions:
// ----------- Obtain world settings controller
CWorldSettingsController *GetWSC(void)
{
CWorldSettingsController *pwsc = NULL;
// obtain bcg viewer
CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer();
if( penBcgViewer != NULL)
{
// obtain world settings controller
pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController;
}
return pwsc;
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
// obtain world settings controller
CWorldSettingsController *pwsc = GetWSC();
if( pwsc == NULL) {
return FALSE;
}
FLOAT tmNow = _pTimer->CurrentTick();
if (ee.ee_slEvent==EVENTCODE_EActivate)
{
switch(m_bctType)
{
case BCT_PYRAMID_PLATES:
pwsc->m_tmPyramidPlatesStart = tmNow;
break;
case BCT_ACTIVATE_PLATE_1:
pwsc->m_tmActivatedPlate1 = tmNow;
pwsc->m_tmDeactivatedPlate1 = 1e6;
break;
case BCT_ACTIVATE_PLATE_2:
pwsc->m_tmActivatedPlate2 = tmNow;
pwsc->m_tmDeactivatedPlate2 = 1e6;
break;
case BCT_ACTIVATE_PLATE_3:
pwsc->m_tmActivatedPlate3 = tmNow;
pwsc->m_tmDeactivatedPlate3 = 1e6;
break;
case BCT_ACTIVATE_PLATE_4:
pwsc->m_tmActivatedPlate4 = tmNow;
pwsc->m_tmDeactivatedPlate4 = 1e6;
break;
case BCT_ACTIVATE_PYRAMID_MORPH_ROOM:
pwsc->m_tmPyramidMorphRoomActivated = tmNow;
break;
}
}
else if (ee.ee_slEvent==EVENTCODE_EDeactivate)
{
switch(m_bctType)
{
case BCT_ACTIVATE_PLATE_1:
pwsc->m_tmDeactivatedPlate1 = tmNow;
break;
case BCT_ACTIVATE_PLATE_2:
pwsc->m_tmDeactivatedPlate2 = tmNow;
break;
case BCT_ACTIVATE_PLATE_3:
pwsc->m_tmDeactivatedPlate3 = tmNow;
break;
case BCT_ACTIVATE_PLATE_4:
pwsc->m_tmDeactivatedPlate4 = tmNow;
break;
}
}
return FALSE;
}
procedures:
Main()
{
// init model
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_CONTROLLER);
SetModelMainTexture(TEXTURE_CONTROLLER);
return;
}
};

View File

@ -0,0 +1,130 @@
603
%{
#include "Entities/StdH/StdH.h"
%}
enum SprayParticlesType {
0 SPT_NONE "None", // no particles
1 SPT_BLOOD "Blood", // blood
2 SPT_BONES "Bones", // bones
3 SPT_FEATHER "Feather", // feather
4 SPT_STONES "Stones", // stones
5 SPT_WOOD "Wood", // wood
6 SPT_SLIME "Slime", // gizmo/beast slime
7 SPT_LAVA_STONES "Lava Stones", // lava stones
8 SPT_ELECTRICITY_SPARKS "Electricity sparks", // electricity sparks
9 SPT_BEAST_PROJECTILE_SPRAY "Beast projectile spray", // beast projectile explosion sparks
10 SPT_SMALL_LAVA_STONES "Small Lava Stones", // small lava stones
};
// input parameter for spawning a blood spray
event ESpawnSpray {
enum SprayParticlesType sptType, // type of particles
FLOAT fDamagePower, // factor saying how powerfull damage has been
FLOAT fSizeMultiplier, // stretch factor
FLOAT3D vDirection, // dammage direction
CEntityPointer penOwner, // who spawned the spray
};
class CBloodSpray: CRationalEntity {
name "Blood Spray";
thumbnail "";
features "CanBePredictable";
properties:
1 enum SprayParticlesType m_sptType = SPT_NONE, // type of particles
2 FLOAT m_tmStarted = 0.0f, // time when spawned
3 FLOAT3D m_vDirection = FLOAT3D(0,0,0), // dammage direction
5 CEntityPointer m_penOwner, // who spawned the spray
6 FLOAT m_fDamagePower = 1.0f, // power of inflicted damage
8 FLOATaabbox3D m_boxOwner = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f), // bounding box of blood spray's owner
9 FLOAT3D m_vGDir = FLOAT3D(0,0,0), // gravity direction
10 FLOAT m_fGA = 0.0f, // gravity strength
components:
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex"
functions:
// particles
void RenderParticles(void)
{
switch( m_sptType)
{
case SPT_BLOOD:
case SPT_BONES:
case SPT_FEATHER:
case SPT_STONES:
case SPT_WOOD:
case SPT_SLIME:
case SPT_LAVA_STONES:
case SPT_SMALL_LAVA_STONES:
case SPT_BEAST_PROJECTILE_SPRAY:
Particles_BloodSpray(m_sptType, this, m_vGDir, m_fGA, m_boxOwner, m_vDirection, m_tmStarted, m_fDamagePower);
break;
case SPT_ELECTRICITY_SPARKS:
{
Particles_MetalParts(this, m_tmStarted, m_boxOwner, m_fDamagePower);
Particles_DamageSmoke(this, m_tmStarted, m_boxOwner, m_fDamagePower);
Particles_BloodSpray(SPT_BLOOD, this, m_vGDir, m_fGA, m_boxOwner, m_vDirection, m_tmStarted, m_fDamagePower/2.0f);
Particles_ElectricitySparks( this, m_tmStarted, 5.0f, 0.0f, 32);
break;
}
}
};
/************************************************************
* MAIN *
************************************************************/
procedures:
Main( ESpawnSpray eSpawn)
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
SetPredictable(TRUE);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// setup variables
m_sptType = eSpawn.sptType;
m_vDirection = eSpawn.vDirection;
m_penOwner = eSpawn.penOwner;
m_fDamagePower = eSpawn.fDamagePower;
m_tmStarted = _pTimer->CurrentTick();
// if owner doesn't exist (could be destroyed in initialization)
if( eSpawn.penOwner->en_pmoModelObject == NULL)
{
// don't do anything
Destroy();
return;
}
eSpawn.penOwner->en_pmoModelObject->GetCurrentFrameBBox( m_boxOwner);
m_boxOwner.StretchByVector(eSpawn.penOwner->en_pmoModelObject->mo_Stretch*eSpawn.fSizeMultiplier);
if (m_penOwner->GetPhysicsFlags()&EPF_MOVABLE) {
m_vGDir = ((CMovableEntity *)&*m_penOwner)->en_vGravityDir;
m_fGA = ((CMovableEntity *)&*m_penOwner)->en_fGravityA;
} else {
FLOATmatrix3D &m = m_penOwner->en_mRotation;
m_vGDir = FLOAT3D(-m(1,2), -m(2,2), -m(3,2));
m_fGA = 30.0f;
}
FLOAT fWaitTime = 2.0f;
if( m_sptType==SPT_ELECTRICITY_SPARKS)
{
fWaitTime = 4.0f;
}
autowait(fWaitTime);
Destroy();
return;
}
};

385
Sources/Entities/Boneman.es Normal file
View File

@ -0,0 +1,385 @@
305
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Boneman/Boneman.h"
%}
uses "Entities/EnemyBase";
%{
// info structure
static EntityInfo eiBoneman = {
EIBT_BONES, 250.0f,
0.0f, 1.9f, 0.0f, // source (eyes)
0.0f, 1.9f, 0.0f, // target (body)
};
#define BONES_HIT 2.8f
#define FIRE_RIGHT_HAND FLOAT3D( 0.25f, 1.5f, 0.0f)
#define FIRE_LEFT_HAND FLOAT3D(-0.25f, 1.5f, 0.0f)
%}
class CBoneman : CEnemyBase {
name "Boneman";
thumbnail "Thumbnails\\Boneman.tbn";
properties:
2 BOOL m_bFistHit = FALSE, // used for close attack
3 BOOL m_bTouchAnother = FALSE, // another entity touched on far attack
4 CSoundObject m_soFeet, // for running sound
5 BOOL m_bRunSoundPlaying = FALSE,
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
1 model MODEL_BONEMAN "Models\\Enemies\\Boneman\\Boneman.mdl",
2 texture TEXTURE_BONEMAN "Models\\Enemies\\Boneman\\Boneman.tex",
3 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
// ************** BONEMAN PARTS **************
10 model MODEL_BONEMAN_BODY "Models\\Enemies\\Boneman\\Debris\\Body.mdl",
11 model MODEL_BONEMAN_HAND "Models\\Enemies\\Boneman\\Debris\\Hand.mdl",
12 model MODEL_BONEMAN_LEGS "Models\\Enemies\\Boneman\\Debris\\Legs.mdl",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Boneman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Boneman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Boneman\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Boneman\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Boneman\\Sounds\\Kick.wav",
55 sound SOUND_PUNCH "Models\\Enemies\\Boneman\\Sounds\\Punch.wav",
56 sound SOUND_DEATH "Models\\Enemies\\Boneman\\Sounds\\Death.wav",
57 sound SOUND_RUN "Models\\Enemies\\Boneman\\Sounds\\Run.wav",
functions:
void Precache(void) {
CEnemyBase::Precache();
PrecacheSound(SOUND_IDLE );
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_FIRE );
PrecacheSound(SOUND_KICK );
PrecacheSound(SOUND_PUNCH);
PrecacheSound(SOUND_DEATH);
PrecacheSound(SOUND_RUN );
PrecacheModel(MODEL_BONEMAN_BODY);
PrecacheModel(MODEL_BONEMAN_HAND);
PrecacheModel(MODEL_BONEMAN_LEGS);
PrecacheClass(CLASS_PROJECTILE, PRT_BONEMAN_FIRE);
};
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
if (eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) {
str.PrintF(TRANS("%s was ripped apart by a Kleer"),(const char*) strPlayerName);
} else {
str.PrintF(TRANS("%s was killed by a Kleer"),(const char*) strPlayerName);
}
return str;
}
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Boneman.txt");
return fnm;
};
/* Entity info */
void *GetEntityInfo(void) {
return &eiBoneman;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// boneman can't harm boneman
if (!IsOfClass(penInflictor, "Boneman")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
void LeaveStain(BOOL bGrow)
{
// boneman doesn't leave bloody stain
}
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
switch (IRnd()%5) {
case 0: iAnim = BONEMAN_ANIM_WOUNDCRITICAL01; break;
case 1: iAnim = BONEMAN_ANIM_WOUNDCRITICAL02; break;
case 2: iAnim = BONEMAN_ANIM_WOUNDCRITICAL03; break;
case 3: iAnim = BONEMAN_ANIM_FALL01; break;
case 4: iAnim = BONEMAN_ANIM_FALL02; break;
default: ASSERTALWAYS("Boneman unknown damage");
}
StartModelAnim(iAnim, 0);
DeactivateRunningSound();
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = BONEMAN_ANIM_DEATHTOBACK; break;
case 1: iAnim = BONEMAN_ANIM_DEATHTOFRONT; break;
default: ASSERTALWAYS("Boneman unknown death");
}
StartModelAnim(iAnim, 0);
DeactivateRunningSound();
return iAnim;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(BONEMAN_COLLISION_BOX_DEATH);
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(BONEMAN_ANIM_STANDLOOP, AOF_LOOPING|AOF_NORESTART);
DeactivateRunningSound();
};
void WalkingAnim(void) {
StartModelAnim(BONEMAN_ANIM_WALKLOOP, AOF_LOOPING|AOF_NORESTART);
DeactivateRunningSound();
};
void RunningAnim(void) {
StartModelAnim(BONEMAN_ANIM_RUNLOOP, AOF_LOOPING|AOF_NORESTART);
ActivateRunningSound();
};
void RotatingAnim(void) {
StartModelAnim(BONEMAN_ANIM_WALKLOOP, AOF_LOOPING|AOF_NORESTART);
DeactivateRunningSound();
};
// 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);
};
// running sounds
void ActivateRunningSound(void)
{
if (!m_bRunSoundPlaying) {
PlaySound(m_soFeet, SOUND_RUN, SOF_3D|SOF_LOOP);
m_bRunSoundPlaying = TRUE;
}
}
void DeactivateRunningSound(void)
{
m_soFeet.Stop();
m_bRunSoundPlaying = FALSE;
}
/************************************************************
* BLOW UP FUNCTIONS *
************************************************************/
// spawn body parts
void BlowUp(void) {
// get your size
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length());
vNormalizedDamage /= Sqrt(vNormalizedDamage.Length());
vNormalizedDamage *= 0.75f;
FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute);
// spawn debris
Debris_Begin(EIBT_BONES, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 5.0f, 2.0f);
Debris_Spawn(this, this, MODEL_BONEMAN_BODY, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_BONEMAN_HAND, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_BONEMAN_HAND, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_BONEMAN_LEGS, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
// hide yourself (must do this after spawning debris)
SwitchToEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
Fire(EVoid) : CEnemyBase::Fire {
// fire projectile
StartModelAnim(BONEMAN_ANIM_ATTACKCLOSELOOP, 0);
DeactivateRunningSound();
autowait(0.35f);
ShootProjectile(PRT_BONEMAN_FIRE, FIRE_RIGHT_HAND, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.45f);
ShootProjectile(PRT_BONEMAN_FIRE, FIRE_LEFT_HAND, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(FRnd()/3+0.6f);
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit {
// hit
if (CalcDist(m_penEnemy) < BONES_HIT) {
jump HitWithBones();
// jump
} else if (CalcDist(m_penEnemy) < 10.0f) {
jump JumpOnEnemy();
}
// run to enemy
m_fShootTime = _pTimer->CurrentTick() + 0.5f;
return EReturn();
};
// jump on enemy
JumpOnEnemy(EVoid) {
StartModelAnim(BONEMAN_ANIM_ATTACKFAR, 0);
DeactivateRunningSound();
// jump
FLOAT3D vDir = (m_penEnemy->GetPlacement().pl_PositionVector -
GetPlacement().pl_PositionVector).Normalize();
vDir *= !GetRotationMatrix();
vDir *= m_fCloseRunSpeed*1.5f;
vDir(2) = 2.5f;
SetDesiredTranslation(vDir);
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
// animation - IGNORE DAMAGE WOUND -
SpawnReminder(this, 0.5f, 0);
m_iChargeHitAnimation = BONEMAN_ANIM_ATTACKFAR;
m_fChargeHitDamage = 20.0f;
m_fChargeHitAngle = 0.0f;
m_fChargeHitSpeed = 15.0f;
autocall CEnemyBase::ChargeHitEnemy() EReturn;
autowait(0.3f);
return EReturn();
};
// hit with bones
HitWithBones(EVoid) {
// attack with bones
StartModelAnim(BONEMAN_ANIM_ATTACKCLOSELOOP, 0);
DeactivateRunningSound();
// right hand
m_bFistHit = FALSE;
autowait(0.35f);
if (CalcDist(m_penEnemy)<BONES_HIT) { m_bFistHit = TRUE; }
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
autowait(0.10f);
if (CalcDist(m_penEnemy)<BONES_HIT) { m_bFistHit = TRUE; }
if (m_bFistHit) {
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
// damage enemy
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 10.0f, FLOAT3D(0, 0, 0), vDirection);
// push target left
FLOAT3D vSpeed;
GetHeadingDirection(AngleDeg(90.0f), vSpeed);
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
// left hand
m_bFistHit = FALSE;
autowait(0.25f);
if (CalcDist(m_penEnemy)<BONES_HIT) { m_bFistHit = TRUE; }
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
autowait(0.10f);
if (CalcDist(m_penEnemy)<BONES_HIT) { m_bFistHit = TRUE; }
if (m_bFistHit) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 10.0f, FLOAT3D(0, 0, 0), vDirection);
// push target left
FLOAT3D vSpeed;
GetHeadingDirection(AngleDeg(-90.0f), vSpeed);
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
return EReturn();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetHealth(125.0f);
m_fMaxHealth = 125.0f;
en_fDensity = 2000.0f;
// set your appearance
SetModel(MODEL_BONEMAN);
SetModelMainTexture(TEXTURE_BONEMAN);
StandingAnim();
m_sptType = SPT_BONES;
// setup moving speed
m_fWalkSpeed = FRnd() + 2.5f;
m_aWalkRotateSpeed = FRnd()*25.0f + 45.0f;
m_fAttackRunSpeed = FRnd()*3.0f + 10.0f;
m_aAttackRotateSpeed = FRnd()*200 + 600.0f;
m_fCloseRunSpeed = FRnd() + 13.0f;
m_aCloseRotateSpeed = FRnd()*100 + 1000.0f;
// setup attack distances
m_fAttackDistance = 100.0f;
m_fCloseDistance = 30.0f;
m_fStopDistance = 2.0f;
m_fAttackFireTime = 3.0f;
m_fCloseFireTime = 2.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 70.0f;
m_fBodyParts = 4;
m_fDamageWounded = 80.0f;
m_iScore = 1000;
if (m_fStepHeight==-1) {
m_fStepHeight = 4.0f;
}
// set stretch factors for height and width
CEnemyBase::StretchModel();
m_soFeet.Set3DParameters(80.0f, 5.0f, 1.0f, 1.0f);
m_bRunSoundPlaying = FALSE;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,65 @@
105
%{
#include "Entities/StdH/StdH.h"
%}
%{
extern DECL_DLL void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer)
{
CEntity *pen = penToBounce;
CBouncer *pbo = (CBouncer *)penBouncer;
// if it is a movable model and some time has passed from the last jump
if ( (pen->GetRenderType()==CEntity::RT_MODEL) &&
(pen->GetPhysicsFlags()&EPF_MOVABLE) ) {
CMovableEntity *pmen = (CMovableEntity *)pen;
if (pmen->en_penReference==NULL) {
return;
}
// give it speed
FLOAT3D vDir;
AnglesToDirectionVector(pbo->m_aDirection, vDir);
pmen->FakeJump(pmen->en_vIntendedTranslation, vDir, pbo->m_fSpeed,
-pbo->m_fParallelComponentMultiplier, pbo->m_fNormalComponentMultiplier, pbo->m_fMaxExitSpeed, pbo->m_tmControl);
}
}
%}
class CBouncer : CRationalEntity {
name "Bouncer";
thumbnail "Thumbnails\\Bouncer.tbn";
features "HasName";
properties:
1 CTString m_strName "Name" 'N' = "Bouncer",
2 CTString m_strDescription = "",
4 FLOAT m_fSpeed "Speed [m/s]" 'S' = 20.0f,
5 ANGLE3D m_aDirection "Direction" 'D' = ANGLE3D(0,90,0),
6 FLOAT m_tmControl "Control time" 'T' = 5.0f,
7 BOOL m_bEntrySpeed = TRUE,
10 FLOAT m_fMaxExitSpeed "Max exit speed" 'M' = 200.0f,
12 FLOAT m_fNormalComponentMultiplier "Normal component multiplier" 'O' = 1.0f,
13 FLOAT m_fParallelComponentMultiplier "Parallel component multiplier" 'P' = 0.0f,
components:
functions:
procedures:
Main() {
// declare yourself as a brush
InitAsBrush();
SetPhysicsFlags(EPF_BRUSH_FIXED|EPF_NOIMPACT);
SetCollisionFlags(ECF_BRUSH);
// if old flag "entry speed" has been reset
if (!m_bEntrySpeed)
{
// kill normal component by default (same behaviour by default)
m_fNormalComponentMultiplier = 0.0f;
m_bEntrySpeed = TRUE;
}
return;
}
};

420
Sources/Entities/Bullet.es Normal file
View File

@ -0,0 +1,420 @@
502
%{
#include "Entities/StdH/StdH.h"
#define BLOOD_SPILL_RED RGBAToColor(250,20,20,255)
#define BLOOD_SPILL_GREEN RGBAToColor(0,250,0,255)
%}
uses "Entities/BasicEffects";
uses "Engine/Classes/MovableEntity";
// input parameters for bullet
event EBulletInit {
CEntityPointer penOwner, // who launched it
FLOAT fDamage, // damage
};
// hit enum
enum BulletHitType {
0 BHT_NONE "", // none
1 BHT_FLESH "", // flesh
2 BHT_BRUSH_STONE "", // brush stone
3 BHT_BRUSH_SAND "", // brush sand
4 BHT_BRUSH_WATER "", // brush water
5 BHT_BRUSH_UNDER_WATER "", // brush under water
6 BHT_ACID "", // acid
7 BHT_BRUSH_RED_SAND "", // brush red sand
};
%{
void CBullet_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONE);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSAND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSAND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATER);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONENOSOUND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSANDNOSOUND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSANDNOSOUND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATERNOSOUND);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETTRAIL);
}
%}
class export CBullet : CEntity {
name "Bullet";
thumbnail "";
features "ImplementsOnPrecache";
properties:
1 CEntityPointer m_penOwner, // entity which owns it
2 FLOAT m_fDamage = 0.0f, // damage
3 FLOAT3D m_vTarget = FLOAT3D(0,0,0), // bullet target point in space
4 FLOAT3D m_vTargetCopy = FLOAT3D(0,0,0), // copy of bullet target point in space for jitter
6 FLOAT3D m_vHitPoint = FLOAT3D(0,0,0), // hit point
8 INDEX m_iBullet = 0, // bullet for lerped launch
9 enum DamageType m_EdtDamage = DMT_BULLET, // damage type
10 FLOAT m_fBulletSize = 0.0f, // bullet can have radius, for hitting models only
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl"
functions:
/************************************************************
* BULLET LAUNCH *
************************************************************/
// set bullet damage
void SetDamage(FLOAT fDamage) {
m_fDamage = fDamage;
};
// calc jitter target
void CalcTarget(FLOAT fRange) {
// destination in bullet direction
AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, m_vTarget);
m_vTarget *= fRange;
m_vTarget += GetPlacement().pl_PositionVector;
m_vTargetCopy = m_vTarget;
};
void CalcTarget(CEntity *pen, FLOAT fRange) {
FLOAT3D vTarget;
// target body
EntityInfo *peiTarget = (EntityInfo*) (pen->GetEntityInfo());
GetEntityInfoPosition(pen, peiTarget->vTargetCenter, vTarget);
// calculate
m_vTarget = (vTarget - GetPlacement().pl_PositionVector).Normalize();
m_vTarget *= fRange;
m_vTarget += GetPlacement().pl_PositionVector;
m_vTargetCopy = m_vTarget;
};
// calc jitter target - !!! must call CalcTarget first !!!
void CalcJitterTarget(FLOAT fR) {
FLOAT3D vJitter;
/* My Sphere
FLOAT fXZ = FRnd()*360.0f;
FLOAT fXY = FRnd()*360.0f;
// sphere
fR *= FRnd();
vJitter(1) = CosFast(fXZ)*CosFast(fXY)*fR;
vJitter(2) = CosFast(fXZ)*SinFast(fXY)*fR;
vJitter(3) = SinFast(fXZ)*fR;*/
// comp graphics algorithms sphere
FLOAT fZ = FRnd()*2.0f - 1.0f;
FLOAT fA = FRnd()*360.0f;
FLOAT fT = Sqrt(1-(fZ*fZ));
vJitter(1) = fT * CosFast(fA);
vJitter(2) = fT * SinFast(fA);
vJitter(3) = fZ;
vJitter = vJitter*fR*FRnd();
// target
m_vTarget = m_vTargetCopy + vJitter;
};
// calc jitter target asymetric - !!! must call CalcTarget first !!!
void CalcJitterTargetFixed(FLOAT fX, FLOAT fY, FLOAT fJitter) {
FLOAT fRndX = FRnd()*2.0f - 1.0f;
FLOAT fRndY = FRnd()*2.0f - 1.0f;
FLOAT3D vX, vY;
const FLOATmatrix3D &m=GetRotationMatrix();
vX(1) = m(1,1); vX(2) = m(2,1); vX(3) = m(3,1);
vY(1) = m(1,2); vY(2) = m(2,2); vY(3) = m(3,2);
// target
m_vTarget = m_vTargetCopy + (vX*(fX+fRndX*fJitter)) + (vY*(fY+fRndY*fJitter));
};
// launch one bullet
void LaunchBullet(BOOL bSound, BOOL bTrail, BOOL bHitFX)
{
// cast a ray to find bullet target
CCastRay crRay( m_penOwner, GetPlacement().pl_PositionVector, m_vTarget);
crRay.cr_bHitPortals = TRUE;
crRay.cr_bHitTranslucentPortals = TRUE;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
crRay.cr_bPhysical = FALSE;
crRay.cr_fTestR = m_fBulletSize;
FLOAT3D vHitDirection;
AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vHitDirection);
INDEX ctCasts = 0;
while( ctCasts<10)
{
if(ctCasts == 0)
{
// perform first cast
GetWorld()->CastRay(crRay);
}
else
{
// next casts
GetWorld()->ContinueCast(crRay);
}
ctCasts++;
// stop casting if nothing hit
if (crRay.cr_penHit==NULL)
{
break;
}
// apply damage
InflictDirectDamage(crRay.cr_penHit, m_penOwner, m_EdtDamage, m_fDamage,
crRay.cr_vHit, vHitDirection);
m_vHitPoint = crRay.cr_vHit;
// if brush hitted
if (crRay.cr_penHit->GetRenderType()==RT_BRUSH && crRay.cr_pbpoBrushPolygon!=NULL)
{
CBrushPolygon *pbpo = crRay.cr_pbpoBrushPolygon;
FLOAT3D vHitNormal = FLOAT3D(pbpo->bpo_pbplPlane->bpl_plAbsolute);
// obtain surface type
INDEX iSurfaceType = pbpo->bpo_bppProperties.bpp_ubSurfaceType;
BulletHitType bhtType = BHT_BRUSH_STONE;
// get content type
INDEX iContent = pbpo->bpo_pbscSector->GetContentType();
CContentType &ct = GetWorld()->wo_actContentTypes[iContent];
// if this is under water polygon
if( ct.ct_ulFlags&CTF_BREATHABLE_GILLS)
{
// if we hit water surface
if( iSurfaceType==SURFACE_WATER)
{
vHitNormal = -vHitNormal;
bhtType=BHT_BRUSH_WATER;
}
// if we hit stone under water
else
{
bhtType=BHT_BRUSH_UNDER_WATER;
}
}
else
{
if( iSurfaceType==SURFACE_SAND) {bhtType=BHT_BRUSH_SAND;}
if( iSurfaceType==SURFACE_RED_SAND) {bhtType=BHT_BRUSH_RED_SAND;}
if( iSurfaceType==SURFACE_WATER) {bhtType=BHT_BRUSH_WATER;}
}
// spawn hit effect
BOOL bPassable = pbpo->bpo_ulFlags & (BPOF_PASSABLE|BPOF_SHOOTTHRU);
if (!bPassable || iSurfaceType==SURFACE_WATER) {
SpawnHitTypeEffect(bhtType, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, FLOAT3D(0.0f, 0.0f, 0.0f));
}
if(!bPassable) {
break;
}
// if not brush
} else {
// if flesh entity
if (crRay.cr_penHit->GetEntityInfo()!=NULL) {
if( ((EntityInfo*)crRay.cr_penHit->GetEntityInfo())->Eeibt == EIBT_FLESH)
{
CEntity *penOfFlesh = crRay.cr_penHit;
FLOAT3D vHitNormal = (GetPlacement().pl_PositionVector-m_vTarget).Normalize();
FLOAT3D vOldHitPos = crRay.cr_vHit;
FLOAT3D vDistance;
// look behind the entity (for back-stains)
GetWorld()->ContinueCast(crRay);
if( crRay.cr_penHit!=NULL && crRay.cr_pbpoBrushPolygon!=NULL &&
crRay.cr_penHit->GetRenderType()==RT_BRUSH)
{
vDistance = crRay.cr_vHit-vOldHitPos;
vHitNormal = FLOAT3D(crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute);
}
else
{
vDistance = FLOAT3D(0.0f, 0.0f, 0.0f);
vHitNormal = FLOAT3D(0,0,0);
}
if(IsOfClass(penOfFlesh, "Gizmo") ||
IsOfClass(penOfFlesh, "Beast"))
{
// spawn green blood hit spill effect
SpawnHitTypeEffect(BHT_ACID, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, vDistance);
}
else
{
// spawn red blood hit spill effect
SpawnHitTypeEffect(BHT_FLESH, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, vDistance);
}
break;
}
}
// stop casting ray if not brush
break;
}
}
if( bTrail)
{
SpawnTrail();
}
};
// destroy yourself
void DestroyBullet(void) {
Destroy();
};
/************************************************************
* EFFECTS *
************************************************************/
// spawn effect from hit type
void SpawnHitTypeEffect(enum BulletHitType bhtType, BOOL bSound, FLOAT3D vHitNormal, FLOAT3D vHitPoint,
FLOAT3D vDirection, FLOAT3D vDistance)
{
switch (bhtType)
{
case BHT_BRUSH_STONE:
case BHT_BRUSH_SAND:
case BHT_BRUSH_RED_SAND:
case BHT_BRUSH_WATER:
case BHT_BRUSH_UNDER_WATER:
{
// bullet stain
ESpawnEffect ese;
if( bSound)
{
if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONE;};
if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSAND;};
if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSAND;};
if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATER;};
if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATER;};
}
else
{
if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONENOSOUND;};
if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSANDNOSOUND;};
if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSANDNOSOUND;};
if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATERNOSOUND;};
if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATERNOSOUND;};
}
ese.vNormal = vHitNormal;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
FLOAT3D vDirection = (vHitPoint-GetPlacement().pl_PositionVector).Normalize();
// reflect direction arround normal
FLOAT fNx = vHitNormal(1);
FLOAT fNy = vHitNormal(2);
FLOAT fNz = vHitNormal(3);
FLOAT fNV = fNx*vDirection(1) + fNy*vDirection(2) + fNz*vDirection(3);
FLOAT fRVx = vDirection(1) - 2*fNx*fNV;
FLOAT fRVy = vDirection(2) - 2*fNy*fNV;
FLOAT fRVz = vDirection(3) - 2*fNz*fNV;
ese.vStretch = FLOAT3D( fRVx, fRVy, fRVz);
SpawnEffect(vHitPoint, ese);
break;
}
case BHT_FLESH:
case BHT_ACID:
{
// spawn bullet entry wound
ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
// if there is exit wound blood spill place
FLOAT fDistance = vDistance.Length();
if( fDistance>0.01f && !(IRnd()%2) )
{
// spawn bullet exit wound blood patch
ese.betType = BET_BLOODSPILL;
if( bhtType == BHT_ACID)
{
ese.colMuliplier = BLOOD_SPILL_GREEN;
}
else
{
ese.colMuliplier = BLOOD_SPILL_RED;
}
ese.vNormal = vHitNormal;
if (fDistance<25.0f)
{
GetNormalComponent( vDistance/fDistance, vHitNormal, ese.vDirection);
FLOAT fLength = ese.vDirection.Length();
fLength = Clamp( fLength*3, 1.0f, 3.0f);
fDistance = Clamp( log10(fDistance), 0.5, 2.0);
ese.vStretch = FLOAT3D( fDistance, fLength*fDistance, 1.0f);
SpawnEffect(vHitPoint, ese);
}
}
break;
}
}
};
// spawn trail of this bullet
void SpawnTrail(void)
{
// get bullet path positions
const FLOAT3D &v0 = GetPlacement().pl_PositionVector;
const FLOAT3D &v1 = m_vHitPoint;
// calculate distance
FLOAT3D vD = v1-v0;
FLOAT fD = vD.Length();
// if too short
if (fD<1.0f) {
// no trail
return;
}
// length must be such that it doesn't get out of path
FLOAT fLen = Min(20.0f, fD);
// position is random, but it must not make trail go out of path
FLOAT3D vPos;
if (fLen<fD) {
vPos = Lerp(v0, v1, FRnd()*(fD-fLen)/fD);
} else {
vPos = v0;
}
ESpawnEffect ese;
UBYTE ubRndH = UBYTE( 8+FRnd()*32);
UBYTE ubRndS = UBYTE( 8+FRnd()*32);
UBYTE ubRndV = UBYTE( 224+FRnd()*32);
UBYTE ubRndA = UBYTE( 32+FRnd()*128);
ese.colMuliplier = HSVToColor(ubRndH, ubRndS, ubRndV)|ubRndA;
ese.betType = BET_BULLETTRAIL;
ese.vNormal = vD/fD;
ese.vStretch = FLOAT3D(0.1f, fLen, 1.0f);
SpawnEffect(vPos , ese);
}
// spawn effect
void SpawnEffect(const FLOAT3D &vHit, const ESpawnEffect &eSpawnEffect)
{
FLOAT3D vDirection;
vDirection = (m_vTarget-GetPlacement().pl_PositionVector).Normalize();
CPlacement3D plHit = CPlacement3D(vHit-vDirection*0.1f, GetPlacement().pl_OrientationAngle);
CEntityPointer penHit = CreateEntity(plHit , CLASS_BASIC_EFFECT);
penHit->Initialize(eSpawnEffect);
};
procedures:
Main(EBulletInit eInit)
{
// remember the initial parameters
ASSERT(eInit.penOwner!=NULL);
m_penOwner = eInit.penOwner;
m_fDamage = eInit.fDamage;
InitAsVoid();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// for lerped launch
m_iBullet = 0;
return;
};
};

443
Sources/Entities/Camera.es Normal file
View File

@ -0,0 +1,443 @@
220
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/WorldLink";
uses "Entities/Player";
uses "Entities/CameraMarker";
class CCamera : CMovableModelEntity
{
name "Camera";
thumbnail "Thumbnails\\Camera.tbn";
features "HasName", "IsTargetable", "IsImportant";
properties:
1 FLOAT m_tmTime "Time" 'E' = 5.0f, // how long to show the scene
2 FLOAT m_fFOV "FOV" 'F' = 90.0f, // camera fov
5 FLOAT m_fLastFOV = 90.0f,
3 CEntityPointer m_penTarget "Target" 'T' COLOR(C_lBLUE|0xFF),
4 CTString m_strName "Name" 'N' = "Camera",
6 CEntityPointer m_penOnBreak "OnBreak" 'B' COLOR(C_lRED|0xFF),
7 BOOL m_bWideScreen "WideScreen" 'W' = TRUE,
10 FLOAT m_tmAtMarker = 0.0f, // time when current marker was reached
11 FLOAT m_tmDelta = 0.0f, // time to reach next marker
13 FLOAT3D m_vPNp0 = FLOAT3D(0,0,0),
14 FLOAT3D m_vPNp1 = FLOAT3D(0,0,0),
15 FLOAT3D m_vTNp0 = FLOAT3D(0,0,0),
16 FLOAT3D m_vTNp1 = FLOAT3D(0,0,0),
17 FLOAT m_fFOVp0 = 0.0f,
18 FLOAT m_fFOVp1 = 0.0f,
19 FLOAT m_fTFOVp0 = 0.0f,
20 FLOAT m_fTFOVp1 = 0.0f,
31 FLOATquat3D m_qPNp0 = FLOATquat3D(0,0,0,0),
32 FLOATquat3D m_qPNp1 = FLOATquat3D(0,0,0,0),
33 FLOATquat3D m_qANp0 = FLOATquat3D(0,0,0,0),
34 FLOATquat3D m_qANp1 = FLOATquat3D(0,0,0,0),
40 CEntityPointer m_penLast, // previous marker
41 CEntityPointer m_penPlayer, // player viewing this camera
42 CTString m_strDescription = "",
43 BOOL m_bStopMoving = FALSE, // stop moving camera on next target
50 COLOR m_colFade0 = 0, // camera fading color
51 COLOR m_colFade1 = 0,
52 BOOL m_bMoving = FALSE, // set while moving
components:
1 model MODEL_CAMERA "Models\\Editor\\Camera.mdl",
2 texture TEXTURE_CAMERA "Models\\Editor\\Camera.tex"
functions:
// render particles
void RenderParticles(void)
{
if (Particle_GetViewer()==this) {
Particles_ViewerLocal(this);
}
}
// Check if entity is moved on a route set up by its targets
BOOL MovesByTargetedRoute( CTString &strTargetProperty) const
{
strTargetProperty = "Target";
return TRUE;
}
// Check if entity can drop marker for making linked route
BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const
{
fnmMarkerClass = CTFILENAME( "Classes\\CameraMarker.ecl");
strTargetProperty = "Target";
return TRUE;
}
// returns camera description
const CTString &GetDescription(void) const
{
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",(const char*) m_penTarget->GetName());
} else {
((CTString&)m_strDescription).PrintF("-><none>");
}
return m_strDescription;
}
CPlacement3D GetLerpedPlacement(void) const
{
FLOAT fLerpFactor;
if (IsPredictor()) {
fLerpFactor = _pTimer->GetLerpFactor();
} else {
fLerpFactor = _pTimer->GetLerpFactor2();
}
return LerpPlacementsPrecise(en_plLastPlacement, en_plPlacement, fLerpFactor);
//return CMovableEntity::GetLerpedPlacement();
}
void PreMoving()
{
// remember old placement for lerping
en_plLastPlacement = en_plPlacement;
}
void DoMoving()
{
if (!m_bMoving) {
return;
}
// read current tick
FLOAT tmCurrent = _pTimer->CurrentTick();
// lerping is initially enabled
BOOL bLerping = TRUE;
// if we hit a marker
if( tmCurrent > (m_tmAtMarker+m_tmDelta - _pTimer->TickQuantum*3/2))
{
// get markers
CCameraMarker *pcmNm1 = &(CCameraMarker&)*m_penLast;
CCameraMarker *pcmNp0 = &(CCameraMarker&)*m_penTarget;
CCameraMarker *pcmNp1 = &(CCameraMarker&)*pcmNp0->m_penTarget;
CCameraMarker *pcmNp2 = &(CCameraMarker&)*pcmNp1->m_penTarget;
// repeat
FOREVER {
// if there is a trigger at the hit marker
if (pcmNp0->m_penTrigger!=NULL) {
// trigger it
SendToTarget(pcmNp0->m_penTrigger, EET_TRIGGER, m_penPlayer);
}
// if the marker should not be skipped
if (!pcmNp0->m_bSkipToNext) {
// stop skipping
break;
}
// go to next marker immediately
pcmNm1 = pcmNp0;
pcmNp0 = pcmNp1;
pcmNp1 = pcmNp2;
pcmNp2 = (CCameraMarker*)&*pcmNp2->m_penTarget;
// disable lerping
bLerping = FALSE;
}
// update markers for next interval
m_penTarget = pcmNp1;
m_penLast = pcmNp0;
// get markers
CCameraMarker &cmNm1 = *pcmNm1;
CCameraMarker &cmNp0 = *pcmNp0;
CCameraMarker &cmNp1 = *pcmNp1;
CCameraMarker &cmNp2 = *pcmNp2;
// get positions from four markers
const FLOAT3D &vPNm1 = cmNm1.GetPlacement().pl_PositionVector;
const FLOAT3D &vPNp0 = cmNp0.GetPlacement().pl_PositionVector;
const FLOAT3D &vPNp1 = cmNp1.GetPlacement().pl_PositionVector;
const FLOAT3D &vPNp2 = cmNp2.GetPlacement().pl_PositionVector;
ANGLE3D aPNm1 = cmNm1.GetPlacement().pl_OrientationAngle;
ANGLE3D aPNp0 = cmNp0.GetPlacement().pl_OrientationAngle;
ANGLE3D aPNp1 = cmNp1.GetPlacement().pl_OrientationAngle;
ANGLE3D aPNp2 = cmNp2.GetPlacement().pl_OrientationAngle;
FLOAT fFOVm1 = cmNm1.m_fFOV;
FLOAT fFOVp0 = cmNp0.m_fFOV;
FLOAT fFOVp1 = cmNp1.m_fFOV;
FLOAT fFOVp2 = cmNp2.m_fFOV;
m_colFade0 = cmNp0.m_colFade;
m_colFade1 = cmNp1.m_colFade;
// find quaternions for rotations
FLOATquat3D qPNm1; qPNm1.FromEuler(aPNm1);
FLOATquat3D qPNp0; qPNp0.FromEuler(aPNp0);
FLOATquat3D qPNp1; qPNp1.FromEuler(aPNp1);
FLOATquat3D qPNp2; qPNp2.FromEuler(aPNp2);
// make all angles between quaternion pairs acute
if( qPNm1%qPNp0<0 ) {
qPNp0 = -qPNp0;
}
if( qPNp0%qPNp1<0 ) {
qPNp1 = -qPNp1;
}
if( qPNp1%qPNp2<0 ) {
qPNp2 = -qPNp2;
}
// update time and position
m_tmAtMarker = m_tmAtMarker+m_tmDelta;
m_tmDelta = cmNp0.m_fDeltaTime;
m_vPNp0 = vPNp0;
m_vPNp1 = vPNp1;
m_fFOVp0 = fFOVp0;
m_fFOVp1 = fFOVp1;
m_qPNp0 = qPNp0;
m_qPNp1 = qPNp1;
// determine delta time multipliers
FLOAT tmDNm1 = cmNm1.m_fDeltaTime;
FLOAT tmDNp0 = cmNp0.m_fDeltaTime;
FLOAT tmDNp1 = cmNp1.m_fDeltaTime;
FLOAT fD0 = 2*tmDNp0 / (tmDNm1+tmDNp0);
FLOAT fD1 = 2*tmDNp0 / (tmDNp0+tmDNp1);
// determine biases, tensions and continuities
FLOAT fBNp0 = cmNp0.m_fBias;
FLOAT fTNp0 = cmNp0.m_fTension;
FLOAT fCNp0 = cmNp0.m_fContinuity;
FLOAT fBNp1 = cmNp1.m_fBias;
FLOAT fTNp1 = cmNp1.m_fTension;
FLOAT fCNp1 = cmNp1.m_fContinuity;
FLOAT fF00 = (1-fTNp0)*(1-fCNp0)*(1-fBNp0) / 2;
FLOAT fF01 = (1-fTNp0)*(1+fCNp0)*(1+fBNp0) / 2;
FLOAT fF10 = (1-fTNp1)*(1+fCNp1)*(1-fBNp1) / 2;
FLOAT fF11 = (1-fTNp1)*(1-fCNp1)*(1+fBNp1) / 2;
// find tangents for translation
m_vTNp0 = ( (vPNp1-vPNp0) * fF00 + (vPNp0-vPNm1) * fF01) * fD0;
m_vTNp1 = ( (vPNp2-vPNp1) * fF10 + (vPNp1-vPNp0) * fF11) * fD1;
// find tangents for FOV
m_fTFOVp0 = ( (fFOVp1-fFOVp0) * fF00 + (fFOVp0-fFOVm1) * fF01) * fD0;
m_fTFOVp1 = ( (fFOVp2-fFOVp1) * fF10 + (fFOVp1-fFOVp0) * fF11) * fD1;
// find tangents for rotation
FLOATquat3D qTNp0, qTNp1;
qTNp0 = ( Log(qPNp0.Inv()*qPNp1) * fF00 + Log(qPNm1.Inv()*qPNp0) * fF01) * fD0;
qTNp1 = ( Log(qPNp1.Inv()*qPNp2) * fF10 + Log(qPNp0.Inv()*qPNp1) * fF11) * fD1;
// find squad parameters
m_qANp0 = qPNp0*Exp( (qTNp0 - Log(qPNp0.Inv()*qPNp1))/2 );
m_qANp1 = qPNp1*Exp( (Log(qPNp0.Inv()*qPNp1) - qTNp1)/2 );
// check for stop moving
if( cmNp0.m_bStopMoving) {
m_bStopMoving = TRUE;
}
}
// calculate the parameter value and hermit basis
FLOAT fT = (tmCurrent - m_tmAtMarker) / m_tmDelta;
FLOAT fH0 = 2*fT*fT*fT - 3*fT*fT + 1;
FLOAT fH1 = -2*fT*fT*fT + 3*fT*fT;
FLOAT fH2 = fT*fT*fT - 2*fT*fT + fT;
FLOAT fH3 = fT*fT*fT - fT*fT;
// interpolate position, rotation and fov
FLOAT3D vPos = m_vPNp0*fH0 + m_vPNp1*fH1 + m_vTNp0*fH2 + m_vTNp1*fH3;
FLOAT fFOV = m_fFOVp0*fH0 + m_fFOVp1*fH1 + m_fTFOVp0*fH2 + m_fTFOVp1*fH3;
FLOATquat3D qRot = Squad(fT, m_qPNp0, m_qPNp1, m_qANp0, m_qANp1);
FLOATmatrix3D mRot;
qRot.ToMatrix(mRot);
// just cache near polygons for various engine needs
en_vNextPosition = vPos;
en_mNextRotation = mRot;
CacheNearPolygons();
// set new placement
CPlacement3D plNew;
plNew.pl_PositionVector = vPos;
DecomposeRotationMatrixNoSnap(plNew.pl_OrientationAngle, mRot);
SetPlacement_internal(plNew, mRot, TRUE);
// if lerping is disabled
if (!bLerping) {
// make last placement same as this one
en_plLastPlacement = en_plPlacement;
}
// set new fov
m_fLastFOV = m_fFOV;
m_fFOV = fFOV;
}
void PostMoving()
{
if (!m_bMoving) {
return;
}
//
if( m_bStopMoving) {
m_bMoving = FALSE;
// mark for removing from list of movers
en_ulFlags |= ENF_INRENDERING;
SendEvent( EStop());
}
}
procedures:
// routine for playing static camera
PlayStaticCamera()
{
m_bMoving = FALSE;
ECameraStart eStart;
eStart.penCamera = this;
m_penPlayer->SendEvent(eStart);
autowait(m_tmTime);
ECameraStop eStop;
eStop.penCamera=this;
m_penPlayer->SendEvent(eStop);
return;
}
// routine for playing movable camera
PlayMovingCamera()
{
// init camera
ECameraStart eStart;
eStart.penCamera = this;
m_penPlayer->SendEvent(eStart);
// check all markers for correct type and numbers
INDEX ctMarkers=1;
INDEX ctNonSkipped=0;
CCameraMarker *pcm0 = (CCameraMarker*)&*m_penTarget;
CCameraMarker *pcm = (CCameraMarker*)&*pcm0->m_penTarget;
// loop thru markers
while( pcm!=NULL && pcm->m_penTarget!=pcm0)
{
pcm = (CCameraMarker*)&*pcm->m_penTarget;
if (pcm==NULL) {
WarningMessage( "Movable camera - broken link!");
return;
}
if (!pcm->m_bSkipToNext) {
ctNonSkipped++;
}
ctMarkers++;
if (ctMarkers>500) {
WarningMessage( "Movable camera - invalid marker loop!");
return;
}
}
// check if we have enough markers to do smooth interpolation
if( ctMarkers<2) {
WarningMessage( "Movable camera requires at least 2 markers in order to work!");
return;
}
// check if we have enough markers to do smooth interpolation
if( ctNonSkipped<1) {
WarningMessage( "Movable camera requires at least 1 non-skipped marker!");
return;
}
// prepare internal variables
FLOAT tmCurrent = _pTimer->CurrentTick();
m_tmAtMarker = tmCurrent;
m_tmDelta = 0.0f;
m_bStopMoving = FALSE;
m_penLast = pcm; // keep last marker
ASSERT( pcm->m_penTarget == m_penTarget);
pcm = (CCameraMarker*)&*m_penTarget;
m_colFade0 = m_colFade1 = pcm->m_colFade;
// register camera as movable entity
AddToMovers();
m_bMoving = TRUE;
// roll, baby, roll ...
wait() {
on( EStop) : {
ECameraStop eStop;
eStop.penCamera=this;
m_penPlayer->SendEvent(eStop);
return;
}
otherwise() : {
resume;
}
}
// all done for now
return;
}
// determine camera type and jump to corresponding routine
PlayCamera()
{
// eventually add to movers list
CCameraMarker &cm = (CCameraMarker&)*m_penTarget;
// if we have at least one marker
if( &cm!=NULL) {
// treat camera as movable
jump PlayMovingCamera();
// if there isn't any markers
} else {
// treat camera as fixed
jump PlayStaticCamera();
}
}
Main()
{
// init as model
InitAsEditorModel();
SetPhysicsFlags(EPF_MOVABLE);
SetCollisionFlags(ECF_CAMERA);
// set appearance
FLOAT fSize = 5.0f;
GetModelObject()->mo_Stretch = FLOAT3D(fSize, fSize, fSize);
SetModel(MODEL_CAMERA);
SetModelMainTexture(TEXTURE_CAMERA);
m_fLastFOV = m_fFOV;
if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Camera Marker")) {
WarningMessage( "Entity '%s' is not of Camera Marker class!",(const char*) m_penTarget->GetName());
m_penTarget = NULL;
}
while(TRUE)
{
wait() {
on (ETrigger eTrigger) : {
if( IsDerivedFromClass(eTrigger.penCaused, "Player")) {
m_penPlayer = eTrigger.penCaused;
call PlayCamera();
}
}
}
};
// cease to exist
Destroy();
return;
};
};

View File

@ -0,0 +1,69 @@
224
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
class CCameraMarker: CMarker
{
name "Camera Marker";
thumbnail "Thumbnails\\CameraMarker.tbn";
properties:
1 FLOAT m_fDeltaTime "Delta time" 'D' = 5.0f,
2 FLOAT m_fBias "Bias" 'B' = 0.0f,
3 FLOAT m_fTension "Tension" 'E' = 0.0f,
4 FLOAT m_fContinuity "Continuity" 'C' = 0.0f,
5 BOOL m_bStopMoving "Stop moving" 'O' = FALSE,
6 FLOAT m_fFOV "FOV" 'F' = 90.0f,
7 BOOL m_bSkipToNext "Skip to next" 'S' = FALSE,
8 COLOR m_colFade "Fade Color" 'C' = 0, // camera fading color
9 CEntityPointer m_penTrigger "Trigger" 'G', // camera triggers when at this marker
components:
1 model MODEL_MARKER "Models\\Editor\\CameraMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\CameraMarker.tex"
functions:
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const
{
fnmMarkerClass = CTFILENAME("Classes\\CameraMarker.ecl");
strTargetProperty = "Target";
return TRUE;
}
procedures:
Main()
{
// clamp parameters
m_fDeltaTime = ClampDn( m_fDeltaTime, 0.001f);
m_fBias = Clamp( m_fBias, -1.0f, +1.0f);
m_fTension = Clamp( m_fTension, -1.0f, +1.0f);
m_fContinuity = Clamp( m_fContinuity, -1.0f, +1.0f);
// init model
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Camera Marker")) {
WarningMessage( "Entity '%s' is not of Camera Marker class!",(const char*) m_penTarget->GetName());
m_penTarget = NULL;
}
return;
}
};

View File

@ -0,0 +1,604 @@
506
%{
#include "Entities/StdH/StdH.h"
#include "Models/Weapons/Cannon/Projectile/CannonBall.h"
#include "Entities/MovingBrush.h"
#include "Entities/DestroyableArchitecture.h"
%}
uses "Entities/BasicEffects";
uses "Entities/Light";
uses "Entities/PlayerWeapons";
uses "Entities/EnemyBase";
enum CannonBallType {
0 CBT_IRON "",
1 CBT_NUKE "",
};
// input parameter for launching the projectile
event ELaunchCannonBall {
CEntityPointer penLauncher, // who launched it
enum CannonBallType cbtType, // type of cannon ball
FLOAT fLaunchPower, // how fast will cannon be lounched
};
event EForceExplode {
};
%{
// projectile solid
#define ECF_CANNON_BALL ( \
((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_CORPSE|ECBI_MODEL_HOLDER|ECBI_MODEL_HOLDER)<<ECB_TEST) |\
((ECBI_PROJECTILE_SOLID)<<ECB_IS) |\
((ECBI_MODEL|ECBI_MODEL_HOLDER|ECBI_CORPSE)<<ECB_PASS) )
#define IRON_LIFE_TIME 10.0f
#define NUKE_LIFE_TIME 5.0f
#define CANNONBALL_STRETCH 3.0f
// damages
#define IRON_DAMAGE_MIN 400.0f
#define IRON_DAMAGE_MAX 750.0f
#define IRON_RANGE_DAMAGE (25.0f/4) // because we have 4 explosions //50
#define IRON_RANGE_HOTSPOT 2.0f //2
#define IRON_RANGE_FALLOFF 16.0f //8
#define NUKE_DAMAGE_MIN 600.0f
#define NUKE_DAMAGE_MAX 800.0f
#define NUKE_RANGE_DAMAGE (1000.0f/13) // because we have 13 explosions
#define NUKE_RANGE_HOTSPOT 15.0f
#define NUKE_RANGE_FALLOFF 50.0f
#define SOUND_RANGE 250.0f
#define STRETCH_0 FLOAT3D(0.0f,0.0f,0.0f)
#define STRETCH_1 FLOAT3D(1.0f,1.0f,1.0f)
#define STRETCH_2 FLOAT3D(2.0f,2.0f,2.0f)
#define STRETCH_3 FLOAT3D(3.0f,3.0f,3.0f)
#define STRETCH_4 FLOAT3D(4.0f,4.0f,4.0f)
#define STRETCH_6 FLOAT3D(6.0f,6.0f,6.0f)
#define STRETCH_8 FLOAT3D(8.0f,8.0f,8.0f)
#define STRETCH_10 FLOAT3D(10.0f,10.0f,10.0f)
void CCannonBall_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONEXPLOSIONSTAIN);
pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONSHOCKWAVE);
pdec->PrecacheModel(MODEL_BALL);
pdec->PrecacheTexture(TEXTURE_IRON_BALL);
pdec->PrecacheTexture(TEXTURE_NUKE_BALL);
pdec->PrecacheTexture(TEX_REFL_BWRIPLES01);
pdec->PrecacheTexture(TEX_SPEC_MEDIUM);
pdec->PrecacheSound(SOUND_BALL_BOUNCE);
}
%}
class export CCannonBall : CMovableModelEntity {
name "Cannon ball";
thumbnail "";
features "ImplementsOnPrecache";
properties:
1 CEntityPointer m_penLauncher, // who lanuched it
2 FLOAT m_fLaunchPower = 0.0f, // how fast will cannon be launched
10 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored
11 FLOAT m_fStartTime = 0.0f, // start time when launched
12 INDEX m_iNextChannel = 0, // next channel to play sound on
13 BOOL m_bSelfExploded = FALSE, // if cannonball exploded because of time, not because of impact
// sound channels for bouncing sound
20 CSoundObject m_soBounce0,
21 CSoundObject m_soBounce1,
22 CSoundObject m_soBounce2,
23 CSoundObject m_soBounce3,
24 CSoundObject m_soBounce4,
30 enum CannonBallType m_cbtType = CBT_IRON,
40 FLOAT m_tmInvisibility = 0.0f, // don't render before given time
41 FLOAT m_tmExpandBox = 0.0f, // expand collision after a few seconds
42 FLOAT m_tmForceExplode = 0.0f, // force explosion at given moment
/*
{
CLightSource m_lsLightSource;
}*/
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
2 class CLASS_LIGHT "Classes\\Light.ecl",
// ********* PLAYER ROCKET *********
10 model MODEL_BALL "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl",
11 texture TEXTURE_NUKE_BALL "Models\\Weapons\\Cannon\\Projectile\\NukeBall.tex",
13 texture TEXTURE_IRON_BALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex",
12 sound SOUND_BALL_BOUNCE "Models\\Weapons\\Cannon\\Sounds\\Bounce.wav",
200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex",
211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
functions:
// premoving
void PreMoving(void) {
if (m_tmExpandBox>0) {
if (_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox) {
ChangeCollisionBoxIndexWhenPossible(1);
m_tmExpandBox = 0;
}
}
CMovableModelEntity::PreMoving();
}
void PostMoving(void)
{
CMovableModelEntity::PostMoving();
if (en_vCurrentTranslationAbsolute.Length()<1.0f || // if very slow, allmost standing
_pTimer->CurrentTick()>=m_tmForceExplode || // if forced explosion
(GetCollisionBoxIndex()==0 && // if unable to change collision box for some time
(_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox+0.5f)))
{
SendEvent(EForceExplode());
}
}
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CMovableModelEntity::Read_t(istr);
// setup light source
// SetupLightSource();
}
/* Get static light source information. */
/*
CLightSource *GetLightSource(void)
{
// if (!IsPredictor()) {
// return &m_lsLightSource;
// } else {
return NULL;
// }
}
*/
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
// if time now is inside invisibility time, don't render model
CModelObject *pmo = GetModelObject();
if ( (pmo != NULL) && (_pTimer->GetLerpedCurrentTick() < (m_fStartTime+m_tmInvisibility) ) )
{
// make it invisible
pmo->mo_colBlendColor = 0;
}
else
{
// make it visible
pmo->mo_colBlendColor = C_WHITE|CT_OPAQUE;
}
return CEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
}
/* // Setup light source
void SetupLightSource(void)
{
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DARKLIGHT|LSF_DYNAMIC;
lsNew.ls_rHotSpot = 0.0f;
lsNew.ls_colColor = RGBToColor(128, 128, 128);
lsNew.ls_rFallOff = 5.0f;
lsNew.ls_plftLensFlare = NULL;
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = NULL;
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
}
*/
// render particles
void RenderParticles(void) {
// no particles when not existing
if (GetRenderType()!=CEntity::RT_MODEL) {
return;
}
FLOAT fSpeedRatio = Min( en_vCurrentTranslationAbsolute.Length()/140.0f, 1.0f);
INDEX ctFireParticles = INDEX( (Max( fSpeedRatio-0.5f, 0.0f)*2.0f)*128);
//CPrintF("fSpeedRatio=%g, ctFireParticles=%d\n", fSpeedRatio, ctFireParticles);
if( _pTimer->GetLerpedCurrentTick()-m_fStartTime>0.075)
{
Particles_BeastBigProjectileTrail( this, 2.0f, 1.0f, 0.75f, ctFireParticles);
}
}
void Initialize(void) {
// set appearance
InitAsModel();
SetPhysicsFlags(EPF_MODEL_BOUNCING);
SetCollisionFlags(ECF_CANNON_BALL);
SetModel(MODEL_BALL);
if( m_cbtType == CBT_IRON)
{
SetModelMainTexture(TEXTURE_IRON_BALL);
}
else
{
SetModelMainTexture(TEXTURE_NUKE_BALL);
}
// stretch it
GetModelObject()->StretchModel(FLOAT3D(CANNONBALL_STRETCH, CANNONBALL_STRETCH, CANNONBALL_STRETCH));
ModelChangeNotify();
// reflection texture data
GetModelObject()->mo_toReflection.SetData(GetTextureDataForComponent(TEX_REFL_BWRIPLES01));
// specular texture data
GetModelObject()->mo_toSpecular.SetData(GetTextureDataForComponent(TEX_SPEC_MEDIUM));
// start moving
LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fLaunchPower), (CMovableEntity*)(CEntity*)m_penLauncher);
en_fBounceDampNormal = 0.5f;
en_fBounceDampParallel = 0.75f;
en_fAcceleration = 0.0f;
en_fDeceleration = 5.0f;
en_fCollisionSpeedLimit = 40.0f;
en_fCollisionDamageFactor = 10.0f;
SetHealth(50000.0f);
GetModelObject()->PlayAnim(CANNONBALL_ANIM_FIRESLOW, 0);
};
FLOAT CalculateDamageToInflict(void)
{
FLOAT fMaxDamage = IRON_DAMAGE_MAX;
if(m_cbtType == CBT_NUKE)
{
fMaxDamage = IRON_DAMAGE_MAX;
}
// speed can range from
FLOAT fSpeedRatio = en_vCurrentTranslationAbsolute.Length()/140.0f;
// apply damage to range from 0 to damage max
FLOAT fApplyDamage = Clamp( fSpeedRatio*fMaxDamage, 0.0f, fMaxDamage);
return fApplyDamage;
}
void Explosion(FLOAT3D vCenter,
const FLOAT3D &vStretchExplosion,
const FLOAT3D &vStretchShockwave,
const FLOAT3D &vStretchStain,
BOOL bHasExplosion,
BOOL bHasShockWave,
BOOL bHasStain,
BOOL bHasLight)
{
ESpawnEffect ese;
FLOAT3D vOnPlane;
FLOATplane3D vPlaneNormal;
FLOAT fDistanceToEdge;
// explosion
if( bHasExplosion)
{
ese.colMuliplier = C_WHITE|CT_OPAQUE;
if( bHasLight)
{
ese.betType = BET_CANNON;
}
else
{
ese.betType = BET_CANNON_NOLIGHT;
}
ese.vStretch = vStretchExplosion;
CPlacement3D plHandle = GetPlacement();
plHandle.pl_PositionVector+=vCenter;
SpawnEffect(plHandle, ese);
// spawn sound event in range
if( IsDerivedFromClass( m_penLauncher, "Player")) {
SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, 100.0f);
}
}
// on plane
if (GetNearestPolygon(vOnPlane, vPlaneNormal, fDistanceToEdge)) {
if ((vOnPlane-GetPlacement().pl_PositionVector).Length() < 3.5f) {
if( bHasStain)
{
// wall stain
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_CANNONEXPLOSIONSTAIN;
ese.vNormal = FLOAT3D(vPlaneNormal);
ese.vStretch = vStretchShockwave;
SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0, 0)), ese);
}
if( bHasShockWave)
{
// shock wave horizontal
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_CANNONSHOCKWAVE;
ese.vNormal = FLOAT3D(vPlaneNormal);
ese.vStretch = vStretchShockwave;
SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0, 0)), ese);
}
// shock wave vertical
/*
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_CANNONSHOCKWAVE;
ese.vNormal = FLOAT3D(vPlaneNormal);
ese.vStretch = vStretchShockwave;
SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0.0f, 0)), ese);
*/
// second explosion on plane
/*
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_CANNON_PLANE;
ese.vNormal = FLOAT3D(vPlaneNormal);
ese.vStretch = vStretchExplosion;
SpawnEffect(CPlacement3D(vOnPlane+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese);
*/
}
}
RangeDamage();
};
/************************************************************
* C O M M O N F U N C T I O N S *
************************************************************/
// ball touch his valid target
BOOL BallTouchExplode(CEntityPointer penHit)
{
FLOAT fApplyDamage = CalculateDamageToInflict();
// obtain touched entity health
FLOAT fHealth = 100;
BOOL bForceCannonballToExplode = FALSE;
if (penHit->GetPhysicsFlags()&EPF_MOVABLE) {
fHealth = ((CMovableEntity&)*penHit).GetHealth();
if( IsDerivedFromClass(penHit, "Enemy Base"))
{
bForceCannonballToExplode = ((CEnemyBase&)*penHit).ForcesCannonballToExplode();
}
} else {
if (IsOfClass(penHit, "ModelHolder2")) {
fHealth = ((CLiveEntity&)*penHit).GetHealth();
} else {
return FALSE;
}
}
if (IsOfClass(penHit, "Player")) {
fHealth += ((CPlayer&)*penHit).m_fArmor * 2.0f;
}
// inflict direct damage to kill hitted entity
FLOAT3D vDirection = en_vCurrentTranslationAbsolute;
vDirection.Normalize();
// CPrintF( "Applied damage %g\n", fApplyDamage);
InflictDirectDamage(penHit, m_penLauncher, DMT_CANNONBALL, fApplyDamage,
GetPlacement().pl_PositionVector, vDirection);
return(fApplyDamage <= fHealth || bForceCannonballToExplode);
};
// infilict range damage by cannonball
void RangeDamage(void)
{
if(m_cbtType == CBT_IRON)
{
InflictRangeDamage(m_penLauncher, DMT_CANNONBALL_EXPLOSION, IRON_RANGE_DAMAGE,
GetPlacement().pl_PositionVector, IRON_RANGE_HOTSPOT, IRON_RANGE_FALLOFF);
}
else
{
// nuclear explosion ...
InflictRangeDamage(m_penLauncher, DMT_CANNONBALL_EXPLOSION, NUKE_RANGE_DAMAGE,
GetPlacement().pl_PositionVector, NUKE_RANGE_HOTSPOT, NUKE_RANGE_FALLOFF);
}
};
// spawn effect
void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) {
CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT);
penEffect->Initialize(eSpawnEffect);
};
/************************************************************
* S O U N D S *
************************************************************/
void BounceSound(FLOAT fSpeed) {
FLOAT fVolume = Clamp(fSpeed/6.0f, 0.0f, 1.0f);
if (fVolume<0.1f) {
return;
}
CSoundObject &so = (&m_soBounce0)[m_iNextChannel];
m_iNextChannel = (m_iNextChannel+1)%5;
so.Set3DParameters(70.0f, 10.0f, fVolume, 1.0f);
PlaySound(so, SOUND_BALL_BOUNCE, SOF_3D);
};
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
Bounce(EVoid) {
// if already inside some entity
CEntity *penObstacle;
if (CheckForCollisionNow(0, &penObstacle)) {
// explode now
return EEnd();
}
FLOAT fWaitTime = IRON_LIFE_TIME;
// if this is nuke ball
if(m_cbtType == CBT_NUKE)
{
fWaitTime = NUKE_LIFE_TIME;
}
// bounce loop
wait(fWaitTime) {
on (EBegin) : { resume; }
on (EPass epass) : {
BOOL bHit;
// ignore launcher within 1 second
bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime;
// ignore twister
bHit &= !IsOfClass(epass.penOther, "Twister");
if (bHit)
{
if (BallTouchExplode(epass.penOther)) { stop; }
}
resume;
}
on (ETouch etouch) : {
// explode if touched another cannon ball
if( IsOfClass(etouch.penOther, "Cannon ball"))
{
stop;
}
if( IsOfClass(etouch.penOther, "Moving Brush"))
{
CMovingBrush &br = (CMovingBrush &) *etouch.penOther;
if( br.m_fHealth>0)
{
FLOAT3D vDirection = en_vCurrentTranslationAbsolute;
vDirection.Normalize();
InflictDirectDamage(etouch.penOther, m_penLauncher, DMT_CANNONBALL, CalculateDamageToInflict(),
GetPlacement().pl_PositionVector, vDirection);
m_bSelfExploded = FALSE;
stop;
}
}
if( IsOfClass(etouch.penOther, "DestroyableArchitecture"))
{
CDestroyableArchitecture &br = (CDestroyableArchitecture &) *etouch.penOther;
if( br.m_fHealth>0)
{
FLOAT3D vDirection = en_vCurrentTranslationAbsolute;
vDirection.Normalize();
InflictDirectDamage(etouch.penOther, m_penLauncher, DMT_CANNONBALL, CalculateDamageToInflict(),
GetPlacement().pl_PositionVector, vDirection);
m_bSelfExploded = FALSE;
stop;
}
}
// clear time limit for launcher
//m_fIgnoreTime = 0.0f;
BounceSound(((FLOAT3D&)etouch.plCollision) % en_vCurrentTranslationAbsolute);
resume;
}
on (EForceExplode) : { stop; }
on (EDeath) : { stop; }
on (ETimer) : { stop; }
}
m_bSelfExploded = TRUE;
return EEnd();
};
// --->>> MAIN
Main(ELaunchCannonBall eLaunch) {
// remember the initial parameters
ASSERT(eLaunch.penLauncher!=NULL);
m_penLauncher = eLaunch.penLauncher;
m_fLaunchPower = eLaunch.fLaunchPower;
m_cbtType = eLaunch.cbtType;
m_tmInvisibility = 0.05f;
m_bSelfExploded = FALSE;
m_tmExpandBox = 0.0001f;
// setup time for forced expolding
m_tmForceExplode=_pTimer->CurrentTick()+30.0f;
// initialization
Initialize();
SendEvent(EReturn());
wait() {
on (EBegin) : { resume;}
on (EReturn) : { stop;}
}
// cast ray to check possible collision
FLOAT tmCastCoverPath = _pTimer->TickQuantum*1.5f;
CCastRay crRay(m_penLauncher, GetPlacement(), m_fLaunchPower*tmCastCoverPath);
crRay.cr_bHitTranslucentPortals = FALSE;
crRay.cr_fTestR = 0.75f/2.0f*CANNONBALL_STRETCH;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
GetWorld()->CastRay(crRay);
// can't hurt player time
m_fIgnoreTime = _pTimer->CurrentTick() + 0.1f;
// bounce
m_fStartTime = _pTimer->CurrentTick();
if (crRay.cr_penHit!=NULL && crRay.cr_penHit->GetRenderType()==RT_MODEL)
{
if (BallTouchExplode(crRay.cr_penHit))
{
m_tmForceExplode = _pTimer->CurrentTick()+tmCastCoverPath;
}
}
autocall Bounce() EEnd;
// dissapear
SwitchToEditorModel();
// stop in place
ForceFullStop();
// sound event
ESound eSound;
eSound.EsndtSound = SNDT_EXPLOSION;
eSound.penTarget = m_penLauncher;
SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, SOUND_RANGE));
if(m_cbtType == CBT_IRON)
{
// Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_3, STRETCH_3, STRETCH_3, TRUE, TRUE, TRUE, TRUE);
// autowait(0.15f);
Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, TRUE, TRUE, TRUE);
Explosion( FLOAT3D(1.0f,1.5f,1.5f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, FALSE, FALSE, FALSE);
Explosion( FLOAT3D(-2.0f,1.0f,-1.5f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, FALSE, FALSE, FALSE);
Explosion( FLOAT3D(-1.0f,0.5f,1.0f), STRETCH_4, STRETCH_4, STRETCH_4, TRUE, FALSE, FALSE, FALSE);
}
else if( m_cbtType == CBT_NUKE)
{
Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_6, STRETCH_6, STRETCH_10, TRUE, TRUE, TRUE, TRUE);
autowait(0.15f);
Explosion( FLOAT3D(4.0f,5.0f,5.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.2f);
Explosion( FLOAT3D(-5.0f,3.0f,-4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.15f);
Explosion( FLOAT3D(-3.0f,2.0f,3.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.15f);
Explosion( FLOAT3D(2.0f,1.0f,4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE);
autowait(0.2f);
Explosion( FLOAT3D(-2.0f,5.0f,-4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.18f);
Explosion( FLOAT3D(-3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.25f);
Explosion( FLOAT3D(0.0f,4.0f,-1.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.15f);
Explosion( FLOAT3D(2.0f,0.0f,-3.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE);
autowait(0.25f);
Explosion( FLOAT3D(-1.0f,2.0f,0.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.125f);
Explosion( FLOAT3D(3.0f,1.0f,1.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.1f);
Explosion( FLOAT3D(3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE);
autowait(0.125f);
Explosion( FLOAT3D(3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE);
}
// cease to exist
Destroy();
return;
}
};

182
Sources/Entities/Catman.es Normal file
View File

@ -0,0 +1,182 @@
301
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Catman/CatMan.h"
%}
uses "Entities/EnemyBase";
enum CatmanType {
0 CMT_SOLDIER "Soldier",
1 CMT_GENERAL "General",
2 CMT_ROGUE "Rogue"
};
%{
// info structure
static EntityInfo eiCatman = {
EIBT_FLESH, 140.0f,
0.0f, 2.0f, 0.0f,
0.0f, 1.5f, 0.0f,
};
%}
class CCatman : CEnemyBase {
name "Catman";
thumbnail "Thumbnails\\Catman.tbn";
properties:
1 enum CatmanType m_cmtType "Type" 'T' = CMT_SOLDIER,
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
1 model MODEL_CATMAN "Models\\Enemies\\Catman\\Catman.mdl",
2 texture TEXTURE_SOLDIER "Models\\Enemies\\Catman\\Catman03.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Catman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Catman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Catman\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Catman\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Catman\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Catman\\Sounds\\Death.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return &eiCatman;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// catman can't harm catman
if (!IsOfClass(penInflictor, "Catman")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
switch (IRnd()%3) {
case 0: iAnim = CATMAN_ANIM_WOUND01; break;
case 1: iAnim = CATMAN_ANIM_WOUND02; break;
case 2: iAnim = CATMAN_ANIM_WOUND03; break;
default: ASSERTALWAYS("Catman unknown damage");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = CATMAN_ANIM_DEATH01; break;
case 1: iAnim = CATMAN_ANIM_DEATH02; break;
default: ASSERTALWAYS("Catman unknown death");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(CATMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(CATMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void) {
StartModelAnim(CATMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void) {
StartModelAnim(CATMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
StartModelAnim(CATMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
// 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);
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
Fire(EVoid) : CEnemyBase::Fire {
// wait for a while
StandingAnim();
autowait(0.2f + FRnd()/4);
// fire projectile
StartModelAnim(CATMAN_ANIM_ATTACK02, 0);
ShootProjectile(PRT_CATMAN_FIRE, FLOAT3D(0.0f, 1.5f, 0.5f), ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(FRnd()/3+0.6f);
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);
SetHealth(15.0f);
m_fMaxHealth = 15.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 2000.0f;
// set your appearance
SetModel(MODEL_CATMAN);
SetModelMainTexture(TEXTURE_SOLDIER);
StandingAnim();
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f);
m_fAttackRunSpeed = FRnd()*2.0f + 4.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 4.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 40.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 10.0f;
m_fAttackFireTime = 3.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 35.0f;
m_fBodyParts = 4;
m_fDamageWounded = 0.0f;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,215 @@
// common headers for flesh entity classes
#include <Entities/Debris.h> /* rcg10062001 need enum definition... */
#include <Entities/KeyItem.h> /* rcg10062001 need enum definition... */
#define SURFACE_SAND 9
#define SURFACE_WATER 12
#define SURFACE_RED_SAND 13
// Max ammo
#define MAX_BULLETS INDEX(500)
#define MAX_SHELLS INDEX(100)
#define MAX_ROCKETS INDEX(50)
#define MAX_GRENADES INDEX(50)
//#define MAX_NAPALM INDEX(250)
#define MAX_ELECTRICITY INDEX(400)
#define MAX_IRONBALLS INDEX(30)
//#define MAX_NUKEBALLS INDEX(3)
// Bit shifters for ammo
#define AMMO_BULLETS 0
#define AMMO_SHELLS 1
#define AMMO_ROCKETS 2
#define AMMO_GRENADES 3
//#define AMMO_NAPALM 4
#define AMMO_ELECTRICITY 5
//#define AMMO_NUKEBALLS 6
#define AMMO_IRONBALLS 7
// Ammo mana Value
#define AV_SHELLS INDEX(70)
#define AV_BULLETS INDEX(10)
#define AV_ROCKETS INDEX(150)
#define AV_GRENADES INDEX(150)
#define AV_ELECTRICITY INDEX(250)
#define AV_IRONBALLS INDEX(700)
//#define AV_NUKEBALLS INDEX(1800)
//#define AV_NAPALM INDEX(200)
enum EmptyShellType {
ESL_BULLET = 0,
ESL_SHOTGUN = 1,
ESL_BUBBLE = 2,
ESL_BULLET_SMOKE = 3,
ESL_SHOTGUN_SMOKE = 4,
ESL_COLT_SMOKE = 5,
};
// empty shell launch info
#define MAX_FLYING_SHELLS 32
struct ShellLaunchData {
FLOAT sld_fSize; // size multiplier
FLOAT3D sld_vPos; // launch position
FLOAT3D sld_vSpeed; // launch speed
FLOAT3D sld_vUp; // up vector in moment of launch
FLOAT sld_tmLaunch; // time of launch
EmptyShellType sld_estType; // shell type
};
#define ShellLaunchData_array m_asldData[MAX_FLYING_SHELLS]
// world change
struct WorldChange {
CTString strGroup; // group name
CPlacement3D plLink; // link placement for relative change
INDEX iType; // change type
};
extern struct WorldChange _SwcWorldChange;
// entity info
struct EntityInfo {
EntityInfoBodyType Eeibt; // body type
FLOAT fMass; // mass (in kg)
FLOAT vSourceCenter[3]; // body point (offset from handle) when entity look another entity
FLOAT vTargetCenter[3]; // body point (offset from handle) when entity is target of look
};
// entity info
struct EntityStats {
CTString es_strName;
INDEX es_ctCount;
INDEX es_ctAmmount;
FLOAT es_fValue;
INDEX es_iScore;
inline void Clear() { es_strName.Clear(); }
};
// statistics data for player stats management
struct DECL_DLL PlayerStats {
INDEX ps_iScore;
INDEX ps_iKills;
INDEX ps_iDeaths;
INDEX ps_iSecrets;
TIME ps_tmTime;
PlayerStats(void)
{
ps_iScore = 0;
ps_iKills = 0;
ps_iDeaths = 0;
ps_iSecrets = 0;
ps_tmTime = 0.0f;
}
};
// get info position for entity
DECL_DLL void GetEntityInfoPosition(CEntity *pen, FLOAT *pf, FLOAT3D &vPos);
// get source and target positions for ray cast
DECL_DLL void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget);
// set bool from bool enum type
DECL_DLL void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet);
// send event to target
DECL_DLL void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused = NULL);
// send event in range
DECL_DLL void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange);
// spawn reminder
DECL_DLL CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue);
// spawn flame
//CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource);
// Set components
DECL_DLL void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture,
ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture);
// Add attachment to model
DECL_DLL void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture,
ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture);
// Remove attachment from model
DECL_DLL void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment);
// Kick entity
DECL_DLL void KickEntity(CEntity *penTarget, FLOAT3D vSpeed);
// lens flare variables
extern CLensFlareType _lftStandard;
extern CLensFlareType _lftStandardReflections;
extern CLensFlareType _lftYellowStarRedRing;
extern CLensFlareType _lftYellowStarRedRingFar;
extern CLensFlareType _lftWhiteGlowStarRedRing;
extern CLensFlareType _lftWhiteGlowStar;
extern CLensFlareType _lftWhiteGlowStarNG;
extern CLensFlareType _lftWhiteStarRedRingStreaks;
extern CLensFlareType _lftWhiteStarRedReflections;
extern CLensFlareType _lftBlueStarBlueReflections;
extern CLensFlareType _lftProjectileStarGlow;
extern CLensFlareType _lftProjectileWhiteBubbleGlow;
extern CLensFlareType _lftProjectileYellowBubbleGlow;
extern CLensFlareType _lftPVSpaceShipWindowFlare;
extern CLensFlareType _lftCatmanFireGlow;
extern CLensFlareType _lftWhiteGlowFar;
// init lens flare effects
void InitLensFlares(void);
// close lens flares effects
void CloseLensFlares(void);
DECL_DLL BOOL SetPlayerAppearance(CModelObject *mo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview);
// debugging functions
DECL_DLL const char *PrintConsole(void);
DECL_DLL const char *PrintStack(CEntity *pen);
// debris spawning
DECL_DLL void Debris_Begin(
EntityInfoBodyType Eeibt,
enum DebrisParticlesType dptParticles,
enum BasicEffectType betStain,
FLOAT fEntitySize, // entity size in meters
const FLOAT3D &vSpeed,
const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving
const FLOAT fConeSize, // size multiplier for debris cone
const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply)
const COLOR colDebris=C_WHITE // multiply color
);
DECL_DLL CEntityPointer Debris_Spawn(
CEntity *penSpawner,
CEntity *penComponents,
SLONG idModelComponent,
SLONG idTextureComponent,
SLONG idReflectionTextureComponent,
SLONG idSpecularTextureComponent,
SLONG idBumpTextureComponent,
INDEX iModelAnim,
FLOAT fSize, // size relative to entity size (or 0 for absolute stretch of 1)
const FLOAT3D &vPosRatio);
// get default entity info for given body type
DECL_DLL EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt);
// damage control functions
DECL_DLL FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage);
// Print center screen message
DECL_DLL void PrintCenterMessage(CEntity *penThis, CEntity *penTarget,
const CTString &strMessage, TIME tmLength, enum MessageSound mssSound);
// get name of a key item
DECL_DLL const char *GetKeyName(enum KeyItemType kit);
// get session properties
DECL_DLL inline const CSessionProperties *GetSP(void)
{
return ((const CSessionProperties *)_pNetwork->GetSessionProperties());
}
// i.e. weapon sound when fireing or exploding
DECL_DLL void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange);
// get some player for trigger source if any is existing
DECL_DLL CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning=TRUE);
// precisely lerp between two placement using quaternions
DECL_DLL CPlacement3D LerpPlacementsPrecise(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fRatio);
// obtain game extra damage per enemy and per player
DECL_DLL FLOAT GetGameDamageMultiplier(void);

View File

View File

@ -0,0 +1,157 @@
#ifndef SE_INCL_FLAGS_H
#define SE_INCL_FLAGS_H
#ifdef PRAGMA_ONCE
#pragma once
#endif
// collision flags
#define ECBI_BRUSH (1UL<<0)
#define ECBI_MODEL (1UL<<1)
#define ECBI_PROJECTILE_MAGIC (1UL<<2)
#define ECBI_PROJECTILE_SOLID (1UL<<3)
#define ECBI_ITEM (1UL<<4)
#define ECBI_CORPSE (1UL<<5)
#define ECBI_MODEL_HOLDER (1UL<<6)
#define ECBI_CORPSE_SOLID (1UL<<7)
#define ECBI_PLAYER (1UL<<8)
// standard flag combinations:
/*
* COLLISION COMBINATIONS
*/
#define ECF_IMMATERIAL (0UL)
// brush
#define ECF_BRUSH ( \
((ECBI_MODEL|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_CORPSE|ECBI_CORPSE_SOLID)<<ECB_TEST) |\
((ECBI_BRUSH)<<ECB_IS))
// model
#define ECF_MODEL ( \
((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_MODEL_HOLDER|ECBI_CORPSE_SOLID)<<ECB_TEST) |\
((ECBI_MODEL)<<ECB_IS))
// projectile magic
#define ECF_PROJECTILE_MAGIC ( \
((ECBI_MODEL|ECBI_BRUSH|ECBI_CORPSE|ECBI_CORPSE_SOLID|ECBI_MODEL_HOLDER)<<ECB_TEST) |\
((ECBI_PROJECTILE_MAGIC)<<ECB_IS) |\
((ECBI_MODEL)<<ECB_PASS) )
// projectile solid
#define ECF_PROJECTILE_SOLID ( \
((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_CORPSE|ECBI_CORPSE_SOLID|ECBI_MODEL_HOLDER)<<ECB_TEST) |\
((ECBI_PROJECTILE_SOLID)<<ECB_IS) |\
((ECBI_MODEL|ECBI_PROJECTILE_SOLID)<<ECB_PASS) )
// item
#define ECF_ITEM ( \
((ECBI_MODEL|ECBI_BRUSH)<<ECB_TEST) |\
((ECBI_MODEL)<<ECB_PASS) |\
((ECBI_ITEM)<<ECB_IS))
// touch model
#define ECF_TOUCHMODEL ( \
((ECBI_MODEL)<<ECB_TEST) |\
((ECBI_MODEL)<<ECB_PASS) |\
((ECBI_ITEM)<<ECB_IS))
// corpse
#define ECF_CORPSE ( \
((ECBI_BRUSH|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_TEST) |\
((ECBI_CORPSE)<<ECB_IS))
// large corpse that is not passable, but doesn't collide with itself
#define ECF_CORPSE_SOLID ( \
((ECBI_BRUSH|ECBI_MODEL|ECBI_MODEL_HOLDER|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<<ECB_TEST) |\
((ECBI_CORPSE_SOLID)<<ECB_IS))
// model holder
#define ECF_MODEL_HOLDER ( \
((ECBI_MODEL|ECBI_CORPSE|ECBI_CORPSE_SOLID|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_MODEL_HOLDER)<<ECB_TEST) |\
((ECBI_MODEL_HOLDER)<<ECB_IS))
// debris
#define ECF_DEBRIS ( \
((ECBI_BRUSH)<<ECB_TEST) |\
((ECBI_CORPSE)<<ECB_IS))
// flame
#define ECF_FLAME ( \
((ECBI_MODEL|ECBI_CORPSE_SOLID)<<ECB_TEST) |\
((ECBI_PROJECTILE_MAGIC)<<ECB_IS) |\
((ECBI_MODEL|ECBI_CORPSE_SOLID)<<ECB_PASS) )
// camera
#define ECF_CAMERA ( \
((ECBI_BRUSH)<<ECB_TEST) |\
((ECBI_MODEL)<<ECB_IS) |\
((ECBI_BRUSH)<<ECB_PASS) )
/*
* PHYSIC COMBINATIONS
*/
// model that walks around on feet (CMovableModelEntity)
#define EPF_MODEL_WALKING ( \
EPF_ONBLOCK_CLIMBORSLIDE|EPF_ORIENTEDBYGRAVITY|\
EPF_TRANSLATEDBYGRAVITY|EPF_PUSHABLE|EPF_MOVABLE)
// model that flies around with wings or similar (CMovableModelEntity)
#define EPF_MODEL_FLYING ( \
EPF_ONBLOCK_SLIDE|EPF_ORIENTEDBYGRAVITY|EPF_PUSHABLE|EPF_MOVABLE)
// model that flies around with no gravity orientation (CMovableModelEntity)
#define EPF_MODEL_FREE_FLYING ( \
EPF_ONBLOCK_SLIDE|EPF_PUSHABLE|EPF_MOVABLE)
// model that bounce around (CMovableModelEntity)
#define EPF_MODEL_BOUNCING ( \
EPF_ONBLOCK_BOUNCE|EPF_PUSHABLE|EPF_MOVABLE|EPF_TRANSLATEDBYGRAVITY)
// projectile that flies around with no gravity orientation (CMovableModelEntity)
#define EPF_PROJECTILE_FLYING ( \
EPF_ONBLOCK_STOPEXACT|EPF_PUSHABLE|EPF_MOVABLE)
// model that slides on brushes (CMovableModelEntity)
#define EPF_MODEL_SLIDING (\
EPF_ONBLOCK_SLIDE|EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY|\
EPF_PUSHABLE|EPF_MOVABLE)
// model that fall (CMovableModelEntity)
#define EPF_MODEL_FALL ( \
EPF_ONBLOCK_SLIDE|EPF_PUSHABLE|EPF_MOVABLE|EPF_TRANSLATEDBYGRAVITY)
// model for items
#define EPF_MODEL_ITEM ( \
EPF_ONBLOCK_BOUNCE|EPF_PUSHABLE|EPF_MOVABLE|EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)
// model that is fixed in one place and cannot be moved (CEntity)
#define EPF_MODEL_FIXED (0UL)
// model that can be pushed around by others (CEntity)
#define EPF_MODEL_PUSHAROUND (\
EPF_ONBLOCK_SLIDE|EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY|EPF_PUSHABLE|EPF_MOVABLE)
// model that walks around switches to this when dead (CMovableModelEntity)
#define EPF_MODEL_CORPSE ( \
EPF_ONBLOCK_SLIDE|EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY|\
EPF_PUSHABLE|EPF_MOVABLE)
// model that is not physically present - just a decoration (CEntity)
#define EPF_MODEL_IMMATERIAL (0UL)
// brush that moves around absolute (CMovableBrushEntity)
#define EPF_BRUSH_MOVING (\
EPF_ONBLOCK_PUSH|EPF_RT_SYNCHRONIZED|\
EPF_ABSOLUTETRANSLATE|EPF_NOACCELERATION|EPF_MOVABLE)
// brush that is fixed in one place and cannot be moved (CEntity)
#define EPF_BRUSH_FIXED (0UL)
// brush that is not physically present - just a decoration (CEntity)
#define EPF_BRUSH_IMMATERIAL (0UL)
#endif /* include-once check. */

View File

@ -0,0 +1,65 @@
// interfacing between CGame and entities
#ifndef SE_INCL_GAMEINTERFACE_H
#define SE_INCL_GAMEINTERFACE_H
#ifdef PRAGMA_ONCE
#pragma once
#endif
// controls' declarations
// these define address and size of player controls structure
DECL_DLL extern void *ctl_pvPlayerControls;
DECL_DLL extern const SLONG ctl_slPlayerControlsSize;
// called to compose action packet from current controls
DECL_DLL extern void ctl_ComposeActionPacket(const CPlayerCharacter &pc, CPlayerAction &paAction, BOOL bPreScan);
// game sets this for player hud and statistics
DECL_DLL extern INDEX plr_iHiScore;
// computer's declarations
// type of computer message
enum CompMsgType {
CMT_INFORMATION = 0,
CMT_BACKGROUND = 1,
CMT_WEAPONS = 2,
CMT_ENEMIES = 3,
CMT_STATISTICS = 4,
CMT_COUNT = 5,
};
// type of statistic comp message
enum CompStatType {
CST_SHORT = 1,
CST_DETAIL = 2,
};
// identifier of a computer message
class DECL_DLL CCompMessageID {
public:
enum CompMsgType cmi_cmtType; // message category
CTFileName cmi_fnmFileName; // message filename
BOOL cmi_bRead; // true if message is read
ULONG cmi_ulHash; // filename hash for fast searching
void Clear(void);
void Read_t(CTStream &strm); // throw char *
void Write_t(CTStream &strm); // throw char *
void NewMessage(const CTFileName &fnm);
};
// !=NULL if some player wants to call computer
DECL_DLL extern class CPlayer *cmp_ppenPlayer;
// !=NULL for rendering computer on secondary display in dualhead
DECL_DLL extern class CPlayer *cmp_ppenDHPlayer;
// set to update current message in background mode (for dualhead)
DECL_DLL extern BOOL cmp_bUpdateInBackground;
// set for initial calling computer without rendering game
DECL_DLL extern BOOL cmp_bInitialStart;
#endif /* include-once check. */

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
// init particle effects
void DECL_DLL InitParticles(void);
// close particle effects
void DECL_DLL CloseParticles(void);
// function for rendering local viewer particles
void DECL_DLL Particles_ViewerLocal(CEntity *penView);
// different particle effects
void DECL_DLL Particles_RomboidTrail(CEntity *pen);
void DECL_DLL Particles_RomboidTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_BombTrail(CEntity *pen);
void DECL_DLL Particles_BombTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_FirecrackerTrail(CEntity *pen);
void DECL_DLL Particles_FirecrackerTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_SpiralTrail(CEntity *pen);
void DECL_DLL Particles_SpiralTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_ColoredStarsTrail(CEntity *pen);
void DECL_DLL Particles_ColoredStarsTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_WhiteLineTrail(CEntity *pen);
void DECL_DLL Particles_WhiteLineTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_Fireball01Trail(CEntity *pen);
void DECL_DLL Particles_Fireball01Trail_Prepare(CEntity *pen);
void DECL_DLL Particles_GrenadeTrail(CEntity *pen);
void DECL_DLL Particles_GrenadeTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_CannonBall(CEntity *pen, FLOAT fSpeedRatio);
void DECL_DLL Particles_CannonBall_Prepare(CEntity *pen);
void DECL_DLL Particles_LavaTrail(CEntity *pen);
void DECL_DLL Particles_LavaTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_LavaBombTrail(CEntity *pen, FLOAT fSizeMultiplier);
void DECL_DLL Particles_LavaBombTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_RocketTrail(CEntity *pen, FLOAT fStretch);
void DECL_DLL Particles_RocketTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_BloodTrail(CEntity *pen);
void DECL_DLL Particles_FlameThrower(const CPlacement3D &plThis, const CPlacement3D &plOther,
FLOAT fThisElapsed, FLOAT fOtherElapsed);
void DECL_DLL Particles_Ghostbuster(const FLOAT3D &vSrc, const FLOAT3D &vDst, INDEX ctRays, FLOAT fSize, FLOAT fPower = 1.0f,
FLOAT fKneeDivider = 33.3333333f);
void DECL_DLL Particles_FlameThrower(const CPlacement3D &plThis, const CPlacement3D &plOther,
FLOAT fThisElapsed, FLOAT fOtherElapsed);
INDEX DECL_DLL Particles_FireBreath(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget, FLOAT tmStart, FLOAT tmStop);
INDEX DECL_DLL Particles_Regeneration(CEntity *pen, FLOAT tmStart, FLOAT tmStop, FLOAT fYFactor, BOOL bDeath);
void DECL_DLL Particles_Stardust(CEntity *pen, FLOAT fSize, FLOAT fHeight, enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_Rising(CEntity *pen, FLOAT m_fActivateTime, FLOAT m_fDeactivateTime, FLOAT fStretchAll, FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, FLOAT fSize,
enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_Spiral(CEntity *pen, FLOAT fSize, FLOAT fHeight, enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_Emanate(CEntity *pen, FLOAT fSize, FLOAT fHeight, enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_Fountain(CEntity *pen, FLOAT fSize, FLOAT fHeight, enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_Atomic(CEntity *pen, FLOAT fSize, FLOAT fHeight, enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_BloodSpray( enum SprayParticlesType sptType, CEntity *penSpray, FLOAT3D vGDir, FLOAT fGA, FLOATaabbox3D boxOwner, FLOAT3D vSpilDirection, FLOAT tmStarted, FLOAT fDamagePower);
void DECL_DLL Particles_EmanatePlane(CEntity *pen, FLOAT fSizeX, FLOAT fSizeY, FLOAT fSizeZ,
FLOAT fParticleSize, FLOAT fAway, FLOAT fSpeed,
enum ParticleTexture ptTexture, INDEX ctParticles);
void DECL_DLL Particles_WaterfallFoam(CEntity *pen, FLOAT fSizeX, FLOAT fSizeY, FLOAT fSizeZ,
FLOAT fParticleSize, FLOAT fSpeed, FLOAT fSpeedY, FLOAT fLife, INDEX ctParticles);
void DECL_DLL Particles_SandFlow(CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fBirthTime, FLOAT fDeathTime,
INDEX ctParticles);
void DECL_DLL Particles_WaterFlow( CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fStartTime, FLOAT fStopTime,
INDEX ctParticles);
void DECL_DLL Particles_LavaFlow( CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fStartTime, FLOAT fStopTime,
INDEX ctParticles);
void DECL_DLL Particles_Death(CEntity *pen, TIME tmStart);
void DECL_DLL Particles_Appearing(CEntity *pen, TIME tmStart);
void DECL_DLL Particles_ElectricitySparks( CEntity *pen, FLOAT fTimeAppear, FLOAT fSize, FLOAT fHeight, INDEX ctParticles);
void DECL_DLL Particles_LavaErupting(CEntity *pen, FLOAT fStretchAll, FLOAT fSize,
FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ,
FLOAT fActivateTime);
void DECL_DLL Particles_BeastProjectileTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_BeastProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fHeight, INDEX ctParticles);
void DECL_DLL Particles_BeastBigProjectileTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_BeastBigProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fZOffset, FLOAT fYOffset, INDEX ctParticles);
void DECL_DLL Particles_BeastProjectileDebrisTrail_Prepare(CEntity *pen);
void DECL_DLL Particles_BeastProjectileDebrisTrail(CEntity *pen, FLOAT fSizeMultiplier);
void DECL_DLL Particles_Rain( CEntity *pen, FLOAT fGridSize, INDEX ctGrids, FLOAT fFactor,
CTextureData *ptdRainMap, FLOATaabbox3D &boxRainMap);
void DECL_DLL Particles_Snow( CEntity *pen, FLOAT fGridSize, INDEX ctGrids);
void DECL_DLL Particles_Lightning( FLOAT3D vSrc, FLOAT3D vDst, FLOAT fTimeStart);
void DECL_DLL Particles_BulletSpray(CEntity *pen, FLOAT3D vGDir, enum EffectParticlesType eptType, FLOAT tmSpawn, FLOAT3D vDirection);
void DECL_DLL Particles_MachineBullets( CEntity *pen, TIME tmStart, TIME tmEnd, FLOAT fFrequency);
void DECL_DLL Particles_EmptyShells( CEntity *pen, ShellLaunchData *asldData);
void DECL_DLL Particles_DestroyingObelisk(CEntity *penSpray, FLOAT tmStarted);
void DECL_DLL Particles_DestroyingPylon(CEntity *penSpray, FLOAT3D vDamageDir, FLOAT tmStarted);
void DECL_DLL Particles_HitGround(CEntity *penSpray, FLOAT tmStarted, FLOAT fSizeMultiplier);
void DECL_DLL Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage);
void DECL_DLL Particles_DamageSmoke( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage);
void DECL_DLL Particles_RunningDust_Prepare(CEntity *pen);
void DECL_DLL Particles_RunningDust(CEntity *pen);

View File

@ -0,0 +1,280 @@
#include "../StdH/StdH.h"
#include "Entities/Common/PathFinding.h"
#include "Entities/NavigationMarker.h"
#define PRINTOUT(_dummy)
//#define PRINTOUT(something) something
// open and closed lists of nodes
static CListHead _lhOpen;
static CListHead _lhClosed;
FLOAT NodeDistance(CPathNode *ppn0, CPathNode *ppn1)
{
return (
ppn0->pn_pnmMarker->GetPlacement().pl_PositionVector -
ppn1->pn_pnmMarker->GetPlacement().pl_PositionVector).Length();
}
CPathNode::CPathNode(class CNavigationMarker *penMarker)
{
pn_pnmMarker = penMarker;
pn_ppnParent = NULL;
pn_fG = 0.0f;
pn_fH = 0.0f;
pn_fF = 0.0f;
}
CPathNode::~CPathNode(void)
{
// detach from marker when deleting
ASSERT(pn_pnmMarker!=NULL);
pn_pnmMarker->m_ppnNode = NULL;
}
// get name of this node
const CTString &CPathNode::GetName(void)
{
static CTString strNone="<none>";
if (this==NULL || pn_pnmMarker==NULL) {
return strNone;
} else {
return pn_pnmMarker->GetName();
}
}
// get link with given index or null if no more (for iteration along the graph)
CPathNode *CPathNode::GetLink(INDEX i)
{
if (this==NULL || pn_pnmMarker==NULL) {
ASSERT(FALSE);
return NULL;
}
CNavigationMarker *pnm = pn_pnmMarker->GetLink(i);
if (pnm==NULL) {
return NULL;
}
return pnm->GetPathNode();
}
// add given node to open list, sorting best first
static void SortIntoOpenList(CPathNode *ppnLink)
{
// start at head of the open list
LISTITER(CPathNode, pn_lnInOpen) itpn(_lhOpen);
// while the given node is further than the one in list
while(ppnLink->pn_fF>itpn->pn_fF && !itpn.IsPastEnd()) {
// move to next node
itpn.MoveToNext();
}
// if past the end of list
if (itpn.IsPastEnd()) {
// add to the end of list
_lhOpen.AddTail(ppnLink->pn_lnInOpen);
// if not past end of list
} else {
// add before current node
itpn.InsertBeforeCurrent(ppnLink->pn_lnInOpen);
}
}
// find shortest path from one marker to another
static BOOL FindPath(CNavigationMarker *pnmSrc, CNavigationMarker *pnmDst)
{
ASSERT(pnmSrc!=pnmDst);
CPathNode *ppnSrc = pnmSrc->GetPathNode();
CPathNode *ppnDst = pnmDst->GetPathNode();
PRINTOUT(CPrintF("--------------------\n"));
PRINTOUT(CPrintF("FindPath(%s, %s)\n", ppnSrc->GetName(), ppnDst->GetName()));
// start with empty open and closed lists
ASSERT(_lhOpen.IsEmpty());
ASSERT(_lhClosed.IsEmpty());
// add the start node to open list
ppnSrc->pn_fG = 0.0f;
ppnSrc->pn_fH = NodeDistance(ppnSrc, ppnDst);
ppnSrc->pn_fF = ppnSrc->pn_fG +ppnSrc->pn_fH;
_lhOpen.AddTail(ppnSrc->pn_lnInOpen);
PRINTOUT(CPrintF("StartState: %s\n", ppnSrc->GetName()));
// while the open list is not empty
while (!_lhOpen.IsEmpty()) {
// get the first node from open list (that is, the one with lowest F)
CPathNode *ppnNode = LIST_HEAD(_lhOpen, CPathNode, pn_lnInOpen);
ppnNode->pn_lnInOpen.Remove();
_lhClosed.AddTail(ppnNode->pn_lnInClosed);
PRINTOUT(CPrintF("Node: %s - moved from OPEN to CLOSED\n", ppnNode->GetName()));
// if this is the goal
if (ppnNode==ppnDst) {
PRINTOUT(CPrintF("PATH FOUND!\n"));
// the path is found
return TRUE;
}
// for each link of current node
CPathNode *ppnLink = NULL;
for(INDEX i=0; (ppnLink=ppnNode->GetLink(i))!=NULL; i++) {
PRINTOUT(CPrintF(" Link %d: %s\n", i, ppnLink->GetName()));
// get cost to get to this node if coming from current node
FLOAT fNewG = ppnLink->pn_fG+NodeDistance(ppnNode, ppnLink);
// if a shorter path already exists
if ((ppnLink->pn_lnInOpen.IsLinked() || ppnLink->pn_lnInClosed.IsLinked()) && fNewG>=ppnLink->pn_fG) {
PRINTOUT(CPrintF(" shorter path exists through: %s\n", ppnLink->pn_ppnParent->GetName()));
// skip this link
continue;
}
// remember this path
ppnLink->pn_ppnParent = ppnNode;
ppnLink->pn_fG = fNewG;
ppnLink->pn_fH = NodeDistance(ppnLink, ppnDst);
ppnLink->pn_fF = ppnLink->pn_fG + ppnLink->pn_fH;
// remove from closed list, if in it
if (ppnLink->pn_lnInClosed.IsLinked()) {
ppnLink->pn_lnInClosed.Remove();
PRINTOUT(CPrintF(" %s removed from CLOSED\n", ppnLink->GetName()));
}
// add to open if not in it
if (!ppnLink->pn_lnInOpen.IsLinked()) {
SortIntoOpenList(ppnLink);
PRINTOUT(CPrintF(" %s added to OPEN\n", ppnLink->GetName()));
}
}
}
// if we get here, there is no path
PRINTOUT(CPrintF("PATH NOT FOUND!\n"));
return FALSE;
}
// clear all temporary structures used for path finding
static void ClearPath(CEntity *penThis)
{
{FORDELETELIST(CPathNode, pn_lnInOpen, _lhOpen, itpn) {
delete &itpn.Current();
}}
{FORDELETELIST(CPathNode, pn_lnInClosed, _lhClosed, itpn) {
delete &itpn.Current();
}}
#ifndef NDEBUG
// for each navigation marker in the world
{FOREACHINDYNAMICCONTAINER(penThis->en_pwoWorld->wo_cenEntities, CEntity, iten) {
if (!IsOfClass(iten, "NavigationMarker")) {
continue;
}
CNavigationMarker &nm = (CNavigationMarker&)*iten;
ASSERT(nm.m_ppnNode==NULL);
}}
#endif
}
// find marker closest to a given position
static void FindClosestMarker(
CEntity *penThis, const FLOAT3D &vSrc, CEntity *&penMarker, FLOAT3D &vPath)
{
CNavigationMarker *pnmMin = NULL;
FLOAT fMinDist = UpperLimit(0.0f);
// for each sector this entity is in
{FOREACHSRCOFDST(penThis->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc)
// for each navigation marker in that sector
{FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen)
if (!IsOfClass(pen, "NavigationMarker")) {
continue;
}
CNavigationMarker &nm = (CNavigationMarker&)*pen;
// get distance from source
FLOAT fDist = (vSrc-nm.GetPlacement().pl_PositionVector).Length();
// if closer than best found
if(fDist<fMinDist) {
// remember it
fMinDist = fDist;
pnmMin = &nm;
}
ENDFOR}
ENDFOR}
// if none found
if (pnmMin==NULL) {
// fail
vPath = vSrc;
penMarker = NULL;
return;
}
// return position
vPath = pnmMin->GetPlacement().pl_PositionVector;
penMarker = pnmMin;
}
// find first marker for path navigation
void PATH_FindFirstMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath)
{
// find closest markers to source and destination positions
CNavigationMarker *pnmSrc;
FLOAT3D vSrcPath;
FindClosestMarker(penThis, vSrc, (CEntity*&)pnmSrc, vSrcPath);
CNavigationMarker *pnmDst;
FLOAT3D vDstPath;
FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath);
// if at least one is not found, or if they are same
if (pnmSrc==NULL || pnmDst==NULL || pnmSrc==pnmDst) {
// fail
penMarker = NULL;
vPath = vSrc;
return;
}
// go to the source marker position
vPath = vSrcPath;
penMarker = pnmSrc;
}
// find next marker for path navigation
void PATH_FindNextMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath)
{
// find closest marker to destination position
CNavigationMarker *pnmDst;
FLOAT3D vDstPath;
FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath);
// if at not found, or if same as current
if (pnmDst==NULL || penMarker==pnmDst) {
// fail
penMarker = NULL;
vPath = vSrc;
return;
}
// try to find shortest path to the destination
BOOL bFound = FindPath((CNavigationMarker*)penMarker, pnmDst);
// if not found
if (!bFound) {
// just clean up and fail
delete pnmDst->GetPathNode();
ClearPath(penThis);
penMarker = NULL;
vPath = vSrc;
return;
}
// find the first marker position after current
CPathNode *ppn = pnmDst->GetPathNode();
while (ppn->pn_ppnParent!=NULL && ppn->pn_ppnParent->pn_pnmMarker!=penMarker) {
ppn = ppn->pn_ppnParent;
}
penMarker = ppn->pn_pnmMarker;
// go there
vPath = penMarker->GetPlacement().pl_PositionVector;
// clean up
ClearPath(penThis);
}

View File

@ -0,0 +1,40 @@
#ifndef SE_INCL_PATHFINDING_H
#define SE_INCL_PATHFINDING_H
#ifdef PRAGMA_ONCE
#pragma once
#endif
// temporary structure used for path finding
class DECL_DLL CPathNode {
public:
// cunstruction/destruction
CPathNode(class CNavigationMarker *penMarker);
~CPathNode(void);
// get name of this node
const CTString &GetName(void);
// get link with given index or null if no more (for iteration along the graph)
CPathNode *GetLink(INDEX i);
class CNavigationMarker *pn_pnmMarker; // the marker itself
CListNode pn_lnInOpen; // for linking in open/closed lists
CListNode pn_lnInClosed;
CPathNode *pn_ppnParent; // best found parent in path yet
FLOAT pn_fG; // total cost to get here through the best parent
FLOAT pn_fH; // estimate of distance to the goal
FLOAT pn_fF; // total quality of the path going through this node
};
// find first marker for path navigation
DECL_DLL void PATH_FindFirstMarker(
CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath);
// find next marker for path navigation
DECL_DLL void PATH_FindNextMarker(
CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath);
#endif /* include-once check. */

View File

View File

@ -0,0 +1,373 @@
#if 0 // use this part when manually setting weapon positions
_pShell->DeclareSymbol("persistent user FLOAT wpn_fH[30+1];", &wpn_fH);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fP[30+1];", &wpn_fP);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fB[30+1];", &wpn_fB);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fX[30+1];", &wpn_fX);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fY[30+1];", &wpn_fY);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fZ[30+1];", &wpn_fZ);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fFOV[30+1];", &wpn_fFOV);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fClip[30+1];", &wpn_fClip);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fFX[30+1];", &wpn_fFX);
_pShell->DeclareSymbol("persistent user FLOAT wpn_fFY[30+1];", &wpn_fFY);
// _pShell->DeclareSymbol("persistent user FLOAT wpn_fFZ[30+1];", &wpn_fFZ);
#else
/*
_pShell->DeclareSymbol("user FLOAT wpn_fFX[30+1];", &wpn_fFX);
_pShell->DeclareSymbol("user FLOAT wpn_fFY[30+1];", &wpn_fFY);
*/
#pragma warning(disable: 4305)
wpn_fH[0]=10;
wpn_fH[1]=-1;
wpn_fH[2]=-1;
wpn_fH[3]=-1;
wpn_fH[4]=2;
wpn_fH[5]=2;
wpn_fH[6]=(FLOAT)4;
wpn_fH[7]=(FLOAT)2;
wpn_fH[8]=(FLOAT)2;
wpn_fH[9]=(FLOAT)0.5;
wpn_fH[10]=(FLOAT)-12;
wpn_fH[11]=(FLOAT)4;
wpn_fH[12]=(FLOAT)4.6;
wpn_fH[13]=(FLOAT)0;
wpn_fH[14]=(FLOAT)1;
wpn_fH[15]=(FLOAT)2.2;
wpn_fH[16]=(FLOAT)2.5;
wpn_fH[17]=(FLOAT)0;
wpn_fH[18]=(FLOAT)0;
wpn_fH[19]=(FLOAT)0;
wpn_fH[20]=(FLOAT)0;
wpn_fH[21]=(FLOAT)0;
wpn_fH[22]=(FLOAT)0;
wpn_fH[23]=(FLOAT)0;
wpn_fH[24]=(FLOAT)0;
wpn_fH[25]=(FLOAT)0;
wpn_fH[26]=(FLOAT)0;
wpn_fH[27]=(FLOAT)0;
wpn_fH[28]=(FLOAT)0;
wpn_fH[29]=(FLOAT)0;
wpn_fH[30]=(FLOAT)0;
wpn_fP[0]=0;
wpn_fP[1]=10;
wpn_fP[2]=0;
wpn_fP[3]=0;
wpn_fP[4]=2;
wpn_fP[5]=1;
wpn_fP[6]=(FLOAT)3;
wpn_fP[7]=(FLOAT)0;
wpn_fP[8]=(FLOAT)1;
wpn_fP[9]=(FLOAT)2.5;
wpn_fP[10]=(FLOAT)0;
wpn_fP[11]=(FLOAT)0;
wpn_fP[12]=(FLOAT)2.8;
wpn_fP[13]=(FLOAT)0;
wpn_fP[14]=(FLOAT)3;
wpn_fP[15]=(FLOAT)4.7;
wpn_fP[16]=(FLOAT)6;
wpn_fP[17]=(FLOAT)0;
wpn_fP[18]=(FLOAT)0;
wpn_fP[19]=(FLOAT)0;
wpn_fP[20]=(FLOAT)0;
wpn_fP[21]=(FLOAT)0;
wpn_fP[22]=(FLOAT)0;
wpn_fP[23]=(FLOAT)0;
wpn_fP[24]=(FLOAT)0;
wpn_fP[25]=(FLOAT)0;
wpn_fP[26]=(FLOAT)0;
wpn_fP[27]=(FLOAT)0;
wpn_fP[28]=(FLOAT)0;
wpn_fP[29]=(FLOAT)0;
wpn_fP[30]=(FLOAT)0;
wpn_fB[0]=0;
wpn_fB[1]=6;
wpn_fB[2]=0;
wpn_fB[3]=0;
wpn_fB[4]=0;
wpn_fB[5]=0;
wpn_fB[6]=(FLOAT)0;
wpn_fB[7]=(FLOAT)0;
wpn_fB[8]=(FLOAT)0;
wpn_fB[9]=(FLOAT)0;
wpn_fB[10]=(FLOAT)0;
wpn_fB[11]=(FLOAT)0;
wpn_fB[12]=(FLOAT)0;
wpn_fB[13]=(FLOAT)0;
wpn_fB[14]=(FLOAT)0;
wpn_fB[15]=(FLOAT)0;
wpn_fB[16]=(FLOAT)0;
wpn_fB[17]=(FLOAT)0;
wpn_fB[18]=(FLOAT)0;
wpn_fB[19]=(FLOAT)0;
wpn_fB[20]=(FLOAT)0;
wpn_fB[21]=(FLOAT)0;
wpn_fB[22]=(FLOAT)0;
wpn_fB[23]=(FLOAT)0;
wpn_fB[24]=(FLOAT)0;
wpn_fB[25]=(FLOAT)0;
wpn_fB[26]=(FLOAT)0;
wpn_fB[27]=(FLOAT)0;
wpn_fB[28]=(FLOAT)0;
wpn_fB[29]=(FLOAT)0;
wpn_fB[30]=(FLOAT)0;
wpn_fX[0]=0.08;
wpn_fX[1]=0.23;
wpn_fX[2]=0.19;
wpn_fX[3]=0.19;
wpn_fX[4]=0.12;
wpn_fX[5]=0.13;
wpn_fX[6]=(FLOAT)0.121;
wpn_fX[7]=(FLOAT)0.137;
wpn_fX[8]=(FLOAT)0.17;
wpn_fX[9]=(FLOAT)0.155;
wpn_fX[10]=(FLOAT)0.16;
wpn_fX[11]=(FLOAT)0.204;
wpn_fX[12]=(FLOAT)0.204;
wpn_fX[13]=(FLOAT)0;
wpn_fX[14]=(FLOAT)0.141;
wpn_fX[15]=(FLOAT)0.169;
wpn_fX[16]=(FLOAT)0.17;
wpn_fX[17]=(FLOAT)0;
wpn_fX[18]=(FLOAT)0;
wpn_fX[19]=(FLOAT)0;
wpn_fX[20]=(FLOAT)0;
wpn_fX[21]=(FLOAT)0;
wpn_fX[22]=(FLOAT)0;
wpn_fX[23]=(FLOAT)0;
wpn_fX[24]=(FLOAT)0;
wpn_fX[25]=(FLOAT)0;
wpn_fX[26]=(FLOAT)0;
wpn_fX[27]=(FLOAT)0;
wpn_fX[28]=(FLOAT)0;
wpn_fX[29]=(FLOAT)0;
wpn_fX[30]=(FLOAT)0;
wpn_fY[0]=0;
wpn_fY[1]=-0.28;
wpn_fY[2]=-0.21;
wpn_fY[3]=-0.21;
wpn_fY[4]=-0.22;
wpn_fY[5]=-0.21;
wpn_fY[6]=(FLOAT)-0.213;
wpn_fY[7]=(FLOAT)-0.24;
wpn_fY[8]=(FLOAT)-0.325;
wpn_fY[9]=(FLOAT)-0.515;
wpn_fY[10]=(FLOAT)-0.2;
wpn_fY[11]=(FLOAT)-0.102;
wpn_fY[12]=(FLOAT)-0.306;
wpn_fY[13]=(FLOAT)0;
wpn_fY[14]=(FLOAT)-0.174;
wpn_fY[15]=(FLOAT)-0.232;
wpn_fY[16]=(FLOAT)-0.3;
wpn_fY[17]=(FLOAT)0;
wpn_fY[18]=(FLOAT)0;
wpn_fY[19]=(FLOAT)0;
wpn_fY[20]=(FLOAT)0;
wpn_fY[21]=(FLOAT)0;
wpn_fY[22]=(FLOAT)0;
wpn_fY[23]=(FLOAT)0;
wpn_fY[24]=(FLOAT)0;
wpn_fY[25]=(FLOAT)0;
wpn_fY[26]=(FLOAT)0;
wpn_fY[27]=(FLOAT)0;
wpn_fY[28]=(FLOAT)0;
wpn_fY[29]=(FLOAT)0;
wpn_fY[30]=(FLOAT)0;
wpn_fZ[0]=0;
wpn_fZ[1]=-0.44;
wpn_fZ[2]=-0.1;
wpn_fZ[3]=-0.1;
wpn_fZ[4]=-0.34;
wpn_fZ[5]=-0.364;
wpn_fZ[6]=(FLOAT)-0.285;
wpn_fZ[7]=(FLOAT)-0.328;
wpn_fZ[8]=(FLOAT)-0.24;
wpn_fZ[9]=(FLOAT)-0.130001;
wpn_fZ[10]=(FLOAT)-0.1;
wpn_fZ[11]=(FLOAT)0;
wpn_fZ[12]=(FLOAT)-0.57;
wpn_fZ[13]=(FLOAT)0;
wpn_fZ[14]=(FLOAT)-0.175;
wpn_fZ[15]=(FLOAT)-0.308;
wpn_fZ[16]=(FLOAT)-0.625;
wpn_fZ[17]=(FLOAT)0;
wpn_fZ[18]=(FLOAT)0;
wpn_fZ[19]=(FLOAT)0;
wpn_fZ[20]=(FLOAT)0;
wpn_fZ[21]=(FLOAT)0;
wpn_fZ[22]=(FLOAT)0;
wpn_fZ[23]=(FLOAT)0;
wpn_fZ[24]=(FLOAT)0;
wpn_fZ[25]=(FLOAT)0;
wpn_fZ[26]=(FLOAT)0;
wpn_fZ[27]=(FLOAT)0;
wpn_fZ[28]=(FLOAT)0;
wpn_fZ[29]=(FLOAT)0;
wpn_fZ[30]=(FLOAT)0;
wpn_fFOV[0]=2;
wpn_fFOV[1]=41.5;
wpn_fFOV[2]=57;
wpn_fFOV[3]=57;
wpn_fFOV[4]=41;
wpn_fFOV[5]=52.5;
wpn_fFOV[6]=(FLOAT)49;
wpn_fFOV[7]=(FLOAT)66.9;
wpn_fFOV[8]=(FLOAT)66;
wpn_fFOV[9]=(FLOAT)85.5;
wpn_fFOV[10]=(FLOAT)72;
wpn_fFOV[11]=(FLOAT)80;
wpn_fFOV[12]=(FLOAT)50;
wpn_fFOV[13]=(FLOAT)80;
wpn_fFOV[14]=(FLOAT)70.5;
wpn_fFOV[15]=(FLOAT)52.5;
wpn_fFOV[16]=(FLOAT)50;
wpn_fFOV[17]=(FLOAT)0;
wpn_fFOV[18]=(FLOAT)0;
wpn_fFOV[19]=(FLOAT)0;
wpn_fFOV[20]=(FLOAT)0;
wpn_fFOV[21]=(FLOAT)0;
wpn_fFOV[22]=(FLOAT)0;
wpn_fFOV[23]=(FLOAT)0;
wpn_fFOV[24]=(FLOAT)0;
wpn_fFOV[25]=(FLOAT)0;
wpn_fFOV[26]=(FLOAT)0;
wpn_fFOV[27]=(FLOAT)0;
wpn_fFOV[28]=(FLOAT)0;
wpn_fFOV[29]=(FLOAT)0;
wpn_fFOV[30]=(FLOAT)0;
wpn_fClip[0]=0;
wpn_fClip[1]=0.1;
wpn_fClip[2]=0.1;
wpn_fClip[3]=0.1;
wpn_fClip[4]=0.1;
wpn_fClip[5]=0.1;
wpn_fClip[6]=0.1;
wpn_fClip[7]=0.1;
wpn_fClip[8]=0.1;
wpn_fClip[9]=0.1;
wpn_fClip[10]=0.1;
wpn_fClip[11]=0.1;
wpn_fClip[12]=0.1;
wpn_fClip[13]=0.1;
wpn_fClip[14]=0.1;
wpn_fClip[15]=0.1;
wpn_fClip[16]=0.1;
wpn_fClip[17]=0;
wpn_fClip[18]=0;
wpn_fClip[19]=0;
wpn_fClip[20]=0;
wpn_fClip[21]=0;
wpn_fClip[22]=0;
wpn_fClip[23]=0;
wpn_fClip[24]=0;
wpn_fClip[25]=0;
wpn_fClip[26]=0;
wpn_fClip[27]=0;
wpn_fClip[28]=0;
wpn_fClip[29]=0;
wpn_fClip[30]=0;
wpn_fFX[0]=(FLOAT)0;
wpn_fFX[1]=(FLOAT)0;
wpn_fFX[2]=(FLOAT)0;
wpn_fFX[3]=(FLOAT)0;
wpn_fFX[4]=(FLOAT)0;
wpn_fFX[5]=(FLOAT)0;
wpn_fFX[6]=(FLOAT)0;
wpn_fFX[7]=(FLOAT)0;
wpn_fFX[8]=(FLOAT)-0.1;
wpn_fFX[9]=(FLOAT)0;
wpn_fFX[10]=(FLOAT)0;
wpn_fFX[11]=(FLOAT)0;
wpn_fFX[12]=(FLOAT)0;
wpn_fFX[13]=(FLOAT)0;
wpn_fFX[14]=(FLOAT)-0.1;
wpn_fFX[15]=(FLOAT)0;
wpn_fFX[16]=(FLOAT)0.25;
wpn_fFX[17]=(FLOAT)0;
wpn_fFX[18]=(FLOAT)0;
wpn_fFX[19]=(FLOAT)0;
wpn_fFX[20]=(FLOAT)0;
wpn_fFX[21]=(FLOAT)0;
wpn_fFX[22]=(FLOAT)0;
wpn_fFX[23]=(FLOAT)0;
wpn_fFX[24]=(FLOAT)0;
wpn_fFX[25]=(FLOAT)0;
wpn_fFX[26]=(FLOAT)0;
wpn_fFX[27]=(FLOAT)0;
wpn_fFX[28]=(FLOAT)0;
wpn_fFX[29]=(FLOAT)0;
wpn_fFX[30]=(FLOAT)0;
wpn_fFY[0]=(FLOAT)0;
wpn_fFY[1]=(FLOAT)0;
wpn_fFY[2]=(FLOAT)0;
wpn_fFY[3]=(FLOAT)0;
wpn_fFY[4]=(FLOAT)0;
wpn_fFY[5]=(FLOAT)0;
wpn_fFY[6]=(FLOAT)0;
wpn_fFY[7]=(FLOAT)0;
wpn_fFY[8]=(FLOAT)0.11;
wpn_fFY[9]=(FLOAT)0;
wpn_fFY[10]=(FLOAT)0;
wpn_fFY[11]=(FLOAT)0;
wpn_fFY[12]=(FLOAT)0;
wpn_fFY[13]=(FLOAT)0;
wpn_fFY[14]=(FLOAT)-0.4;
wpn_fFY[15]=(FLOAT)0;
wpn_fFY[16]=(FLOAT)-0.5;
wpn_fFY[17]=(FLOAT)0;
wpn_fFY[18]=(FLOAT)0;
wpn_fFY[19]=(FLOAT)0;
wpn_fFY[20]=(FLOAT)0;
wpn_fFY[21]=(FLOAT)0;
wpn_fFY[22]=(FLOAT)0;
wpn_fFY[23]=(FLOAT)0;
wpn_fFY[24]=(FLOAT)0;
wpn_fFY[25]=(FLOAT)0;
wpn_fFY[26]=(FLOAT)0;
wpn_fFY[27]=(FLOAT)0;
wpn_fFY[28]=(FLOAT)0;
wpn_fFY[29]=(FLOAT)0;
wpn_fFY[30]=(FLOAT)0;
// tommygun
wpn_fH[6]=(FLOAT)4;
wpn_fP[6]=(FLOAT)3;
wpn_fB[6]=(FLOAT)0;
wpn_fX[6]=(FLOAT)0.121;
wpn_fY[6]=(FLOAT)-0.213;
wpn_fZ[6]=(FLOAT)-0.285;
wpn_fFOV[6]=(FLOAT)49;
wpn_fClip[6]=0.1;
wpn_fFX[6]=(FLOAT)0;
wpn_fFY[6]=(FLOAT)0;
// grenade launcher
wpn_fH[9]=(FLOAT)2;
wpn_fP[9]=(FLOAT)6;
wpn_fB[9]=(FLOAT)0;
wpn_fX[9]=(FLOAT)0.14;
wpn_fY[9]=(FLOAT)-0.41;
wpn_fZ[9]=(FLOAT)-0.335001;
wpn_fFOV[9]=(FLOAT)44.5;
wpn_fClip[9]=(FLOAT)0.1;
wpn_fFX[9]=(FLOAT)0;
wpn_fFY[9]=(FLOAT)0;
// iron cannon
wpn_fH[16]=(FLOAT)2.5;
wpn_fP[16]=(FLOAT)6;
wpn_fB[16]=(FLOAT)0;
wpn_fX[16]=(FLOAT)0.225;
wpn_fY[16]=(FLOAT)-0.345;
wpn_fZ[16]=(FLOAT)-0.57;
wpn_fFOV[16]=(FLOAT)57;
wpn_fClip[16]=(FLOAT)0.1;
wpn_fFX[16]=(FLOAT)0.25;
wpn_fFY[16]=(FLOAT)-0.5;
#pragma warning(default: 4305)
#endif

View File

@ -0,0 +1,94 @@
225
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/BasicEffects";
class CCopier : CRationalEntity {
name "Copier";
thumbnail "Thumbnails\\Copier.tbn";
features "HasName", "HasTarget", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Copier",
3 CTString m_strDescription = "",
2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BROWN|0xFF),
4 BOOL m_bSpawnEffect "Spawn Effect" 'X' = TRUE,
components:
1 model MODEL_TELEPORT "Models\\Editor\\Copier.mdl",
2 texture TEXTURE_TELEPORT "Models\\Editor\\Copier.tex",
3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
functions:
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",(const char*) m_penTarget->GetName());
}
return m_strDescription;
}
void TeleportEntity()
{
// if the target doesn't exist, or is destroyed
if (m_penTarget==NULL || (m_penTarget->GetFlags()&ENF_DELETED)) {
// do nothing
return;
}
CEntity *pen = GetWorld()->CopyEntityInWorld( *m_penTarget,
CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) );
// teleport back
CPlacement3D pl = GetPlacement();
pl.pl_PositionVector += GetRotationMatrix().GetColumn(2)*0.05f;
pen->Teleport(pl);
// spawn teleport effect
if (m_bSpawnEffect) {
ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_TELEPORT;
ese.vNormal = FLOAT3D(0,1,0);
FLOATaabbox3D box;
pen->GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm()*2;
ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize);
CEntityPointer penEffect = CreateEntity(GetPlacement(), CLASS_BASIC_EFFECT);
penEffect->Initialize(ese);
}
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_TOUCHMODEL);
// set appearance
SetModel(MODEL_TELEPORT);
SetModelMainTexture(TEXTURE_TELEPORT);
while (TRUE) {
// wait to someone enter and teleport it
wait() {
on (ETrigger eTrigger) : {
if (m_penTarget!=NULL) {
TeleportEntity();
}
stop;
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
};

124
Sources/Entities/Counter.es Normal file
View File

@ -0,0 +1,124 @@
232
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/ModelHolder2";
class CCounter : CRationalEntity {
name "Counter";
thumbnail "Thumbnails\\Counter.tbn";
features "HasName", "IsTargetable", "IsImportant";
properties:
1 FLOAT m_fCountdownSpeed "Countdown speed" 'S' = 12.0f,
2 CEntityPointer m_penTarget "Zero target" 'T' COLOR(C_WHITE|0x80),
3 FLOAT m_fNumber = 0.0f,
4 FLOAT m_tmStart = -1.0f,
5 CTString m_strName "Name" 'N' ="",
6 CSoundObject m_soSound,
7 INDEX m_iCountFrom "Count start" 'A' = 1023,
10 CEntityPointer m_pen0 "Bit 0" COLOR(C_RED|0x30),
11 CEntityPointer m_pen1 "Bit 1" COLOR(C_RED|0x30),
12 CEntityPointer m_pen2 "Bit 2" COLOR(C_RED|0x30),
13 CEntityPointer m_pen3 "Bit 3" COLOR(C_RED|0x30),
14 CEntityPointer m_pen4 "Bit 4" COLOR(C_RED|0x30),
15 CEntityPointer m_pen5 "Bit 5" COLOR(C_RED|0x30),
16 CEntityPointer m_pen6 "Bit 6" COLOR(C_RED|0x30),
17 CEntityPointer m_pen7 "Bit 7" COLOR(C_RED|0x30),
18 CEntityPointer m_pen8 "Bit 8" COLOR(C_RED|0x30),
19 CEntityPointer m_pen9 "Bit 9" COLOR(C_RED|0x30),
components:
0 sound SOUND_TICK "Sounds\\Menu\\Select.wav",
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex"
functions:
void Precache(void)
{
PrecacheSound( SOUND_TICK);
CRationalEntity::Precache();
}
void DisplayNumber(void)
{
for( INDEX iDigit=0; iDigit<10; iDigit++)
{
CModelHolder2 *pmh = (CModelHolder2 *)&*(&m_pen0)[iDigit];
if( pmh!=NULL && pmh->GetModelObject()!=NULL &&
pmh->GetModelObject()->mo_toTexture.GetData()!=NULL)
{
// set texture animation
INDEX iOldAnim = pmh->GetModelObject()->mo_toTexture.GetAnim();
INDEX iAnim=(INDEX(m_fNumber)&(1<<iDigit))>>iDigit;
pmh->GetModelObject()->mo_toTexture.PlayAnim(iAnim, 0);
// play sound
m_soSound.Set3DParameters(200.0f, 100.0f, 1.0f,
Clamp(1.0f+(m_iCountFrom-m_fNumber)/m_iCountFrom*2.0f, 1.0f, 3.0f) );
if( iDigit==0 && iOldAnim!=iAnim /*iOldAnim==1 && iAnim==0 */&& !m_soSound.IsPlaying())
{
PlaySound(m_soSound, SOUND_TICK, SOF_3D|SOF_VOLUMETRIC);
}
}
}
}
procedures:
CountDown()
{
while( TRUE)
{
autowait(_pTimer->TickQuantum);
FLOAT tmNow = _pTimer->CurrentTick();
FLOAT tmDelta = tmNow-m_tmStart;
FLOAT fSub = Clamp( tmDelta/m_fCountdownSpeed, 0.01f, 1.0f);
m_fNumber = Clamp( m_fNumber-fSub, 0.0f, FLOAT(m_iCountFrom));
DisplayNumber();
if( m_fNumber==0)
{
return EReturn();
}
}
}
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
autowait(0.1f);
m_fNumber = m_iCountFrom;
DisplayNumber();
wait() {
on(EBegin): {
resume;
}
on (ETrigger eTrigger): {
m_fNumber = m_iCountFrom;
DisplayNumber();
m_tmStart = _pTimer->CurrentTick();
call CountDown();
}
on(EReturn): {
if( m_penTarget!= NULL)
{
SendToTarget(m_penTarget, EET_TRIGGER);
}
stop;
}
}
return;
}
};

View File

@ -0,0 +1,214 @@
341
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Mental/Mental.h"
#include "Models/CutSequences/CrateRider/Crate.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
%{
// info structure
static EntityInfo eiCrate = {
EIBT_FLESH, 500.0f,
0.0f, 1.5f, 0.0f, // source (eyes)
0.0f, 1.0f, 0.0f, // target (body)
};
#define GREET_SENSE_RANGE 10.0f
#define GREET_SENSE_DELAY 10.0f
%}
class CCrateRider: CEnemyBase {
name "CrateRider";
thumbnail "Thumbnails\\Mental.tbn";
properties:
// class internal
1 CTFileName m_fnmHeadTex1 "Head texture1" 'H' = CTString(""),
2 CTFileName m_fnmHeadTex2 "Head texture2" = CTString(""),
3 CTFileName m_fnmDriveSnd "Drive sound" 'S' = CTString(""),
{
CAutoPrecacheSound m_aps;
CAutoPrecacheTexture m_apt1;
CAutoPrecacheTexture m_apt2;
}
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
2 class CLASS_DEBRIS "Classes\\Debris.ecl",
3 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl",
4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** DATA **************
10 model MODEL_MENTAL "Models\\Enemies\\Mental\\Mental.mdl",
11 texture TEXTURE_MENTAL "Models\\Enemies\\Mental\\Mental.tex",
12 model MODEL_HEAD "Models\\Enemies\\Mental\\Head.mdl",
13 model MODEL_CRATE "Models\\CutSequences\\CrateRider\\Crate.mdl",
14 texture TEXTURE_CRATE "Models\\CutSequences\\CrateRider\\Crate.tex",
15 texture TEXTURE_BUMP "Models\\CutSequences\\Bridge\\BridgeBump.tex",
functions:
/* Entity info */
void *GetEntityInfo(void)
{
return &eiCrate;
};
void Precache(void)
{
CEnemyBase::Precache();
PrecacheClass(CLASS_DEBRIS);
m_apt1.Precache(m_fnmHeadTex1);
m_apt2.Precache(m_fnmHeadTex2);
m_aps.Precache(m_fnmDriveSnd);
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
iAnim = 0;
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
iAnim = 0;
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
// ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(CRATE_ANIM_DEFAULT, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE);
CModelObject *pmo0 = &(GetModelObject()->GetAttachmentModel(0)->amo_moModelObject);
pmo0->PlayAnim(MENTAL_ANIM_CRATEANIMLEFTSEATING, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE);
CModelObject *pmo1 = &(GetModelObject()->GetAttachmentModel(1)->amo_moModelObject);
pmo1->PlayAnim(MENTAL_ANIM_CRATEANIMRIGHTSEATING, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE);
m_soSound.Stop();
};
void WalkingAnim(void) {
RunningAnim();
StartModelAnim(CRATE_ANIM_DRIVE, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void)
{
if (m_fnmDriveSnd!="") {
PlaySound(m_soSound, m_fnmDriveSnd, SOF_3D);
}
CModelObject *pmo0 = &(GetModelObject()->GetAttachmentModel(0)->amo_moModelObject);
pmo0->PlayAnim(MENTAL_ANIM_CRATEANIMLEFT, AOF_LOOPING|AOF_NORESTART);
CModelObject *pmo1 = &(GetModelObject()->GetAttachmentModel(1)->amo_moModelObject);
pmo1->PlayAnim(MENTAL_ANIM_CRATEANIMRIGHT, AOF_LOOPING|AOF_NORESTART);
StartModelAnim(CRATE_ANIM_DRIVE, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
RunningAnim();
};
// 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);
};
void AddRider(INDEX i, const CTFileName &fnmHead)
{
AddAttachment(i, MODEL_MENTAL, TEXTURE_MENTAL);
CModelObject *pmoMain = &(GetModelObject()->GetAttachmentModel(i)->amo_moModelObject);
// pmoMain->PlayAnim(i==0 ? MENTAL_ANIM_CRATEANIMLEFTSEATING : MENTAL_ANIM_CRATEANIMRIGHTSEATING, AOF_LOOPING);
pmoMain->PlayAnim(i==0 ? MENTAL_ANIM_CRATEANIMLEFT: MENTAL_ANIM_CRATEANIMRIGHT, AOF_LOOPING);
AddAttachmentToModel(this, *pmoMain, 0, MODEL_HEAD, TEXTURE_MENTAL, 0, 0, 0);
CModelObject *pmoHead = &(pmoMain->GetAttachmentModel(0)->amo_moModelObject);
if (fnmHead!="") {
// try to
try {
pmoHead->mo_toTexture.SetData_t(fnmHead);
// if anything failed
} catch (char *strError) {
// report error
CPrintF("%s\n", strError);
}
}
}
procedures:
/************************************************************
* 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);
SetHealth(1.0f);
m_fMaxHealth = 1.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 2000.0f;
m_fBlowUpSize = 2.0f;
// set your appearance
SetModel(MODEL_CRATE);
SetModelMainTexture(TEXTURE_CRATE);
AddRider(0, m_fnmHeadTex1);
AddRider(1, m_fnmHeadTex2);
// setup moving speed
m_fWalkSpeed =
m_fAttackRunSpeed =
m_fCloseRunSpeed = 1.0f;
m_aWalkRotateSpeed = AngleDeg(30.0f);
m_aAttackRotateSpeed = AngleDeg(30);
m_aCloseRotateSpeed = AngleDeg(30);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 5.0f; // greeting distance
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 0.0f;
m_fBodyParts = 4;
m_fDamageWounded = 1.0f;
m_iScore = 0;
m_bBlind = TRUE;
m_bRobotBlowup = TRUE;
// m_fSenseRange = GREET_SENSE_RANGE;
// set stretch factors for height and width
const FLOAT fSize = 0.6f;
GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize));
ModelChangeNotify();
StandingAnim();
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

743
Sources/Entities/Cyborg.es Normal file
View File

@ -0,0 +1,743 @@
330
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Cyborg/Cyborg.h"
%}
uses "Entities/EnemyFly";
uses "Entities/Projectile";
uses "Entities/CyborgBike";
enum CyborgType {
0 CBT_GROUND "Ground",
1 CBT_FLY "Fly",
2 CBT_FLYGROUND "Fly-Ground",
};
%{
// info structure
static EntityInfo eiCyborgStand = {
EIBT_ROBOT, 200.0f,
0.0f, 1.55f, 0.0f,
0.0f, 1.0f, 0.0f,
};
static EntityInfo eiCyborgFly = {
EIBT_ROBOT, 1500.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
#define FIRE_BIKE FLOAT3D(-0.35f, 0.1f, -1.2f)
#define FIRE_LASER FLOAT3D(-0.5f, 1.7f, -0.75f)
#define IGNORE_RANGE 400.0f
#define BIKE_ATTACHMENT FLOAT3D(0, 0, -0.271f)
%}
class CCyborg : CEnemyBase {
name "Cyborg";
thumbnail "Thumbnails\\Cyborg.tbn";
properties:
1 enum CyborgType m_EctType "Type" 'T' = CBT_GROUND, // type
2 INDEX m_iCloseHit = 0, // close hit hand (left or right)
3 INDEX m_iFireLaserCount = 0, // fire laser binary divider
4 INDEX m_ctBombsToDrop = 0, // counter of bombs to drop in fly-over
10 FLOAT m_tmLastBombDropped = -1.0f, // when last bomb was dropped
5 FLOAT m_fFlyAboveEnemy = 0.0f, // fly above enemy height
6 FLOAT m_fFlySpeed = 0.0f,
7 FLOAT m_aFlyRotateSpeed = 0.0f,
8 FLOAT m_fFallStartTime = 0.0f,
9 BOOL m_bBombing "Bombing" 'B' = FALSE, // enable bombing
{
CEntity *penBullet; // bullet
}
components:
0 class CLASS_BASE "Classes\\EnemyFly.ecl",
1 class CLASS_BULLET "Classes\\Bullet.ecl",
2 class CLASS_CYBORG_BIKE "Classes\\CyborgBike.ecl",
3 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
10 model MODEL_CYBORG "Models\\Enemies\\Cyborg\\Cyborg.mdl",
11 model MODEL_ASS "Models\\Enemies\\Cyborg\\AssHole.mdl",
12 model MODEL_TORSO "Models\\Enemies\\Cyborg\\Torso.mdl",
13 model MODEL_HEAD "Models\\Enemies\\Cyborg\\Head.mdl",
14 model MODEL_RIGHT_UPPER_ARM "Models\\Enemies\\Cyborg\\RightUpperArm.mdl",
15 model MODEL_RIGHT_LOWER_ARM "Models\\Enemies\\Cyborg\\RightLowerArm.mdl",
16 model MODEL_LEFT_UPPER_ARM "Models\\Enemies\\Cyborg\\LeftUpperArm.mdl",
17 model MODEL_LEFT_LOWER_ARM "Models\\Enemies\\Cyborg\\LeftLowerArm.mdl",
18 model MODEL_RIGHT_UPPER_LEG "Models\\Enemies\\Cyborg\\RightUpperLeg.mdl",
19 model MODEL_RIGHT_LOWER_LEG "Models\\Enemies\\Cyborg\\RightLowerLeg.mdl",
20 model MODEL_LEFT_UPPER_LEG "Models\\Enemies\\Cyborg\\LeftUpperLeg.mdl",
21 model MODEL_LEFT_LOWER_LEG "Models\\Enemies\\Cyborg\\LeftLowerLeg.mdl",
22 model MODEL_FOOT "Models\\Enemies\\Cyborg\\Foot.mdl",
23 model MODEL_BIKE "Models\\Enemies\\Cyborg\\Bike.mdl",
30 texture TEXTURE_CYBORG "Models\\Enemies\\Cyborg\\Cyborg.tex",
31 texture TEXTURE_BIKE "Models\\Enemies\\Cyborg\\Bike.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Cyborg\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Cyborg\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Cyborg\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Cyborg\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Cyborg\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Cyborg\\Sounds\\Death.wav",
// ************** REFLECTIONS **************
202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
// ************** SPECULAR **************
211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex",
functions:
/* Entity info */
void *GetEntityInfo(void) {
if (m_EctType!=CBT_GROUND) {
return &eiCyborgFly;
} else {
return &eiCyborgStand;
}
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// cyborg can't harm cyborg
if (!IsOfClass(penInflictor, "Cyborg")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
switch (IRnd()%4) {
case 0: iAnim = CYBORG_ANIM_WOUND01; break;
case 1: iAnim = CYBORG_ANIM_WOUND02; break;
case 2: iAnim = CYBORG_ANIM_WOUND03; break;
case 3: iAnim = CYBORG_ANIM_WOUND04; break;
default: ASSERTALWAYS("Cyborg unknown damage");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = CYBORG_ANIM_DEATH01; break;
case 1: iAnim = CYBORG_ANIM_DEATH02; break;
default: ASSERTALWAYS("Cyborg unknown death");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// virtual anim functions
void StandingAnim(void) {
if (m_EctType!=CBT_GROUND) {
StartModelAnim(CYBORG_ANIM_BIKEREST, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(CYBORG_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART);
}
};
void WalkingAnim(void) {
if (m_EctType!=CBT_GROUND) {
StartModelAnim(CYBORG_ANIM_BIKEREST, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(CYBORG_ANIM_WALK01, AOF_LOOPING|AOF_NORESTART);
}
};
void RunningAnim(void) {
if (m_EctType!=CBT_GROUND) {
StartModelAnim(CYBORG_ANIM_BIKEREST, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(CYBORG_ANIM_WALK01, AOF_LOOPING|AOF_NORESTART);
}
};
void RotatingAnim(void) {
if (m_EctType!=CBT_GROUND) {
StartModelAnim(CYBORG_ANIM_BIKEREST, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(CYBORG_ANIM_WALK01, AOF_LOOPING|AOF_NORESTART);
}
};
void ChangeCollisionToAir() {
ChangeCollisionBoxIndexWhenPossible(CYBORG_COLLISION_BOX_BIKE);
};
void ChangeCollisionToGround() {
ChangeCollisionBoxIndexWhenPossible(CYBORG_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);
};
/************************************************************
* BLOW UP FUNCTIONS *
************************************************************/
// spawn body parts
void BlowUp(void) {
// get your size
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
// spawn debris
Debris_Begin(EIBT_ROBOT, DPR_SMOKETRAIL, BET_EXPLOSIONSTAIN, fEntitySize, m_vDamage*0.3f,
en_vCurrentTranslationAbsolute, 1.0f, 0.0f);
Debris_Spawn(this, this, MODEL_ASS, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_TORSO, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_STRONG, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_HEAD, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_RIGHT_UPPER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_RIGHT_LOWER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_LEFT_UPPER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_LEFT_LOWER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_RIGHT_UPPER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_RIGHT_LOWER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_LEFT_UPPER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_LEFT_LOWER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_FOOT, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_FOOT, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0,
0, 0.0f, FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
// spawn explosion
CPlacement3D plExplosion = GetPlacement();
CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT);
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_BOMB;
FLOAT fSize = fEntitySize*0.3f;
eSpawnEffect.vStretch = FLOAT3D(fSize,fSize,fSize);
penExplosion->Initialize(eSpawnEffect);
// hide yourself (must do this after spawning debris)
SwitchToEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
};
/************************************************************
* MOVING FUNCTIONS *
************************************************************/
// fly desired position for attack
virtual void FlyDesiredPosition(FLOAT3D &vPos) {
FLOAT fDist = (m_penEnemy->GetPlacement().pl_PositionVector -
GetPlacement().pl_PositionVector).Length();
vPos = m_penEnemy->GetPlacement().pl_PositionVector;
vPos += FLOAT3D(m_penEnemy->en_mRotation(1, 2),
m_penEnemy->en_mRotation(2, 2),
m_penEnemy->en_mRotation(3, 2)) * m_fFlyAboveEnemy;
};
// fly move in direction
void FlyInDirection() {
/* !!!!
RotateToAngle();
// determine translation speed
FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation;
vTranslation(1) = 0.0f;
vTranslation.Normalize();
vTranslation *= m_fMoveSpeed;
// start moving
SetDesiredTranslation(vTranslation);
*/
};
// fly entity to desired position
void FlyToPosition() {
/* !!!!
CalcAngleFromPosition();
FlyInDirection();
*/
};
procedures:
/************************************************************
* CLASS INTERNAL *
************************************************************/
// fall to floor
FallToFloor(EVoid) {
// spawn bike
CPlacement3D plBike = GetPlacement();
FLOATmatrix3D mRotation;
MakeRotationMatrixFast(mRotation, GetPlacement().pl_OrientationAngle);
plBike.pl_PositionVector += BIKE_ATTACHMENT*mRotation;
ECyborgBike ecb;
ecb.fSpeed = m_fFlySpeed*2.0f;
CEntityPointer penBike = CreateEntity(plBike, CLASS_CYBORG_BIKE);
penBike->Initialize(ecb);
// drop to floor
m_EctType = CBT_GROUND;
SetPhysicsFlags(EPF_MODEL_WALKING);
ChangeCollisionToGround();
// remove bike
RemoveAttachmentFromModel(*GetModelObject(), CYBORG_ATTACHMENT_BIKE);
// anim
if (IRnd()&1) {
StartModelAnim(CYBORG_ANIM_FALL01, 0);
} else {
StartModelAnim(CYBORG_ANIM_FALL02, 0);
}
// wait to touch brush or time limit
m_fFallStartTime = _pTimer->CurrentTick();
wait (10.0f) {
on (EBegin) : { resume; }
// brush touched
on (ETouch et) : {
if (et.penOther->GetRenderType()&RT_BRUSH) {
StopMoving();
stop;
}
resume;
}
on (EDamage) : { resume; }
on (EWatch) : { resume; }
on (ETimer) : { stop; }
}
// wait fall anim
if (_pTimer->CurrentTick() < m_fFallStartTime+1.5f) {
wait(m_fFallStartTime+1.5f - _pTimer->CurrentTick()) {
on (EBegin) : { resume; }
on (EDamage) : { resume; }
on (EWatch) : { resume; }
on (ETimer) : { stop; }
}
}
return EReturn();
};
// get up
GetUp(EVoid) {
// get up
StartModelAnim(CYBORG_ANIM_GETUP, 0);
wait(GetModelObject()->GetAnimLength(CYBORG_ANIM_GETUP)) {
on (EBegin) : { resume; }
on (EDamage) : { resume; }
on (EWatch) : { resume; }
on (ETimer) : { stop; }
}
return EReturn();
};
/************************************************************
* PROCEDURES WHEN NO ANY SPECIAL ACTION *
************************************************************/
// Move to destination
/* !!!!
MoveToDestination(EVoid) : CEnemyBase::MoveToDestination {
// animation
if (m_bRunToMarker) {
RunningAnim();
} else {
WalkingAnim();
}
// fly to position
if (m_EctType!=CBT_GROUND) {
m_fMoveFrequency = 0.25f;
m_fMovePrecision = m_fMoveSpeed*m_fMoveFrequency*2.0f;
while ((m_vDesiredPosition-GetPlacement().pl_PositionVector).Length()>m_fMovePrecision) {
wait (0.25f) {
on (EBegin) : { FlyToPosition(); }
on (ETimer) : { stop; }
}
}
return EReturn();
// move to position
} else {
jump CEnemyBase::MoveToDestination();
}
};
*/
/************************************************************
* PROCEDURES WHEN HARMED *
************************************************************/
// Play wound animation and falling body part
BeWounded(EDamage eDamage) : CEnemyBase::BeWounded {
// damage only on ground
if (m_EctType==CBT_GROUND) {
jump CEnemyBase::BeWounded(eDamage);
// fall on ground
} else if (m_EctType==CBT_FLYGROUND && GetHealth()<=60.0f) {
SetHealth(60.0f);
m_fMaxHealth = 60.0f;
autocall FallToFloor() EReturn;
autocall GetUp() EReturn;
SendEvent(ERestartAttack());
}
return EReturn();
};
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
AttackEnemy(EVoid) : CEnemyBase::AttackEnemy {
// air attack
if (m_EctType!=CBT_GROUND) {
jump FlyAttackEnemy();
// ground attack
} else if (TRUE) {
jump CEnemyBase::AttackEnemy();
}
};
// fly attack enemy
FlyAttackEnemy(EVoid) {
// initial preparation
autocall CEnemyBase::InitializeAttack() EReturn;
// while you have some enemy
while (m_penEnemy != NULL) {
// to far cease attack
if (CalcDist(m_penEnemy) > IGNORE_RANGE) {
SetTargetNone();
}
if (m_penEnemy != NULL) {
// attack run
if (SeeEntity(m_penEnemy, CosFast(90.0f))) {
autocall FlyAttackRun() EReturn;
// go away and rotate
} else if (TRUE) {
autocall GoAwayAndRotate() EReturn;
}
}
}
// stop attack
autocall CEnemyBase::StopAttack() EReturn;
// return to Move() procedure
return EBegin();
};
// fly attack run
FlyAttackRun(EVoid) {
m_iFireLaserCount = 0;
if (m_bBombing) {
m_ctBombsToDrop = 3;
}
while (SeeEntity(m_penEnemy, CosFast(90.0f))) {
m_fMoveFrequency = 0.1f;
wait(m_fMoveFrequency) {
on (EBegin) : {
if (IsInFrustum(m_penEnemy, CosFast(55.0f))) {
// fire laser
if (m_iFireLaserCount==0) {
ShootProjectile(PRT_CYBORG_LASER, FIRE_BIKE, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
}
if (m_iFireLaserCount++ == 2) {
m_iFireLaserCount = 0;
}
}
// if a bomb may be dropped
if (m_ctBombsToDrop>0 && _pTimer->CurrentTick()>=m_tmLastBombDropped+0.3f) {
// calculate where it would hit
FLOAT fV = en_vCurrentTranslationAbsolute.Length();
FLOAT fD = CalcDist(m_penEnemy);
FLOAT fDP = CalcPlaneDist(m_penEnemy);
FLOAT fH = Sqrt(fD*fD-fDP*fDP);
FLOAT fHitD = fDP-fV*Sqrt(2*fH/en_fGravityA);
// if close enough
if( Abs(fHitD)<10.0f) {
// drop it
CPlacement3D pl(FLOAT3D(FRnd()*2.0f-1.0f, -1.0f, 0.0f), ANGLE3D(0, 0, 0)); ;
pl.RelativeToAbsoluteSmooth(GetPlacement());
CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE);
ELaunchProjectile eLaunch;
eLaunch.penLauncher = this;
eLaunch.prtType = PRT_CYBORG_BOMB;
eLaunch.fSpeed = fV;
penProjectile->Initialize(eLaunch);
m_ctBombsToDrop--;
m_tmLastBombDropped = _pTimer->CurrentTick();
}
}
// inside attack radius
if (MayMoveToAttack()) {
m_fMoveSpeed = m_fFlySpeed;
m_aRotateSpeed = m_aFlyRotateSpeed;
FlyDesiredPosition(m_vDesiredPosition);
FlyToPosition();
RunningAnim();
// outside attack radius
} else {
StopMoving();
StandingAnim();
}
}
on (ETimer) : { stop; }
}
}
return EReturn();
};
GoAwayAndRotate(EVoid) {
// go away
SetDesiredTranslation(FLOAT3D(0, 1.25f, -m_fFlySpeed));
StopRotating();
autowait(1.0f);
// rotate side
if (IRnd()&1) {
SetDesiredRotation(ANGLE3D( 100.0f, 0, 0));
} else {
SetDesiredRotation(ANGLE3D(-100.0f, 0, 0));
}
// rotate to enemy
SetDesiredTranslation(FLOAT3D(0, 0, -m_fFlySpeed));
while (!SeeEntityInPlane(m_penEnemy, CosFast(5.0f))) {
autowait(_pTimer->TickQuantum);
}
return EReturn();
};
Fire(EVoid) : CEnemyBase::Fire {
// to fire
StartModelAnim(CYBORG_ANIM_TOFIRE, 0);
m_fLockOnEnemyTime = GetModelObject()->GetAnimLength(CYBORG_ANIM_TOFIRE) + FRnd()/3;
autocall CEnemyBase::LockOnEnemy() EReturn;
StartModelAnim(CYBORG_ANIM_FIRE02, 0);
ShootProjectile(PRT_CYBORG_LASER, FIRE_LASER, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
m_fLockOnEnemyTime = 0.5f;
autocall CEnemyBase::LockOnEnemy() EReturn;
StartModelAnim(CYBORG_ANIM_FIRE02, 0);
ShootProjectile(PRT_CYBORG_LASER, FIRE_LASER, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
m_fLockOnEnemyTime = 0.5f;
autocall CEnemyBase::LockOnEnemy() EReturn;
StartModelAnim(CYBORG_ANIM_FIRE02, 0);
ShootProjectile(PRT_CYBORG_LASER, FIRE_LASER, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.1f + FRnd()/3);
m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/3.0f);
// from fire
StartModelAnim(CYBORG_ANIM_FROMFIRE, 0);
autowait(GetModelObject()->GetAnimLength(CYBORG_ANIM_FROMFIRE));
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit {
// animation
m_iCloseHit = IRnd()&1;
if (m_iCloseHit==0) {
StartModelAnim(CYBORG_ANIM_ATTACKCLOSE01, 0);
} else {
StartModelAnim(CYBORG_ANIM_ATTACKCLOSE02, 0);
}
autowait(0.9f);
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
if (CalcDist(m_penEnemy)<m_fCloseDistance) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 15.0f, FLOAT3D(0, 0, 0), vDirection);
// push target left/right
FLOAT3D vSpeed;
if (m_iCloseHit==0) {
GetHeadingDirection(AngleDeg(90.0f), vSpeed);
} else {
GetHeadingDirection(AngleDeg(-90.0f), vSpeed);
}
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
return EReturn();
};
/************************************************************
* D E A T H *
************************************************************/
Death(EVoid) : CEnemyBase::Death {
StopMoving(); // stop moving
DeathSound(); // death sound
// death notify (usually change collision box and change body density)
ChangeCollisionBoxIndexWhenPossible(CYBORG_COLLISION_BOX_DEATH);
// set physic flags
SetPhysicsFlags(EPF_MODEL_CORPSE);
SetCollisionFlags(ECF_CORPSE);
if (m_EctType==CBT_FLY || m_EctType==CBT_FLYGROUND) {
autocall FallToFloor() EReturn;
} else if (TRUE) {
// start death anim
INDEX iAnim = AnimForDeath();
autowait(GetModelObject()->GetAnimLength(iAnim));
}
// death twist
StartModelAnim(CYBORG_ANIM_DEATHTWIST, AOF_LOOPING);
autowait(FRnd()*5.0f + 1.0f);
StartModelAnim(CYBORG_ANIM_DEATHREST, 0);
// explode
SetHealth(-45.0f);
ReceiveDamage(NULL, DMT_EXPLOSION, 10.0f, FLOAT3D(0,0,0), FLOAT3D(0,1,0));
return EEnd();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
en_fDensity = 5000.0f;
// set your appearance
SetModel(MODEL_CYBORG);
SetModelMainTexture(TEXTURE_CYBORG);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_ASS,
MODEL_ASS, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_TORSO,
MODEL_TORSO, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_STRONG, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_HEAD,
MODEL_HEAD, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_RIGHTUPPERARM,
MODEL_RIGHT_UPPER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_RIGHTLOWERARM,
MODEL_RIGHT_LOWER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_LEFTUPPERARM,
MODEL_LEFT_UPPER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_LEFTLOWERARM,
MODEL_LEFT_LOWER_ARM, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_RIGHTUPPERLEG,
MODEL_RIGHT_UPPER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_RIGHTLOWERLEG,
MODEL_RIGHT_LOWER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_LEFTUPPERLEG,
MODEL_LEFT_UPPER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_LEFTLOWERLEG,
MODEL_LEFT_LOWER_LEG, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_FOOTRIGHT,
MODEL_FOOT, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_FOOTLEFT,
MODEL_FOOT, TEXTURE_CYBORG, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
if (m_EctType!=CBT_GROUND) {
AddAttachmentToModel(this, *GetModelObject(), CYBORG_ATTACHMENT_BIKE,
MODEL_BIKE, TEXTURE_BIKE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
// fly in air
SetHealth(90.0f);
m_fMaxHealth = 90.0f;
ChangeCollisionToAir();
SetPhysicsFlags(EPF_MODEL_FLYING);
m_iScore = 1000;
} else {
// walk on ground
SetHealth(60.0f);
m_fMaxHealth = 60.0f;
ChangeCollisionToGround();
SetPhysicsFlags(EPF_MODEL_WALKING);
m_iScore = 500;
}
StandingAnim();
// setup moving speed
m_fWalkSpeed = FRnd()*3.0f + 6.0f;
m_aWalkRotateSpeed = FRnd()*20.0f + 700.0f;
m_fAttackRunSpeed = m_fWalkSpeed;
m_aAttackRotateSpeed = m_aWalkRotateSpeed;
m_fCloseRunSpeed = m_fWalkSpeed;
m_aCloseRotateSpeed = m_aWalkRotateSpeed;
m_fWalkSpeed/=3;
// setup attack distances
m_fAttackDistance = 100.0f;
m_fCloseDistance = 2.5f;
m_fStopDistance = 1.5;
m_fAttackFireTime = 3.0f;
m_fCloseFireTime = 2.0f;
m_fIgnoreRange = 200.0f;
// fly moving properties
m_fFlyAboveEnemy = 10.0f+FRnd()*1.0f;
m_fFlySpeed = FRnd()*5.0f + 20.0f;
m_aFlyRotateSpeed = FRnd()*25.0f + 100.0f;
// damage/explode properties
m_fBlowUpAmount = 90.0f;
m_fDamageWounded = 50.0f;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,132 @@
331
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Cyborg/Bike.h"
%}
uses "Entities/BasicEffects";
uses "Entities/Debris";
event ECyborgBike {
FLOAT fSpeed,
};
%{
static EntityInfo eiCyborgBike = {
EIBT_FLESH, 1300.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
%}
class CCyborgBike : CMovableModelEntity {
name "Cyborg Bike";
thumbnail "";
properties:
1 FLOAT m_fSpeed = 0.0f,
2 INDEX m_iIndex = 0,
components:
1 class CLASS_DEBRIS "Classes\\Debris.ecl",
2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** BIKE **************
10 model MODEL_BIKE "Models\\Enemies\\Cyborg\\Bike.mdl",
11 texture TEXTURE_BIKE "Models\\Enemies\\Cyborg\\Bike.tex",
// ************** REFLECTIONS **************
202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
// ************** SPECULAR **************
211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
functions:
procedures:
/************************************************************
* M A I N L O O P *
************************************************************/
// main loop
MainLoop(EVoid) {
SetDesiredTranslation(FLOAT3D(0, -(2.0f+FRnd()*2.0f), -m_fSpeed));
SetDesiredRotation(ANGLE3D(0, 0, 0));
// wait to touch brush or time limit or death
wait (10.0f) {
on (EBegin) : { resume; }
// brush touched
on (ETouch et) : {
if (et.penOther->GetRenderType()&RT_BRUSH) {
SetDesiredTranslation(FLOAT3D(0, 0, 0));
SetDesiredRotation(ANGLE3D(0, 0, 0));
stop;
}
resume;
}
on (EDamage) : { resume; }
on (EDeath) : { stop; }
on (ETimer) : { stop; }
}
// hide yourself
SwitchToEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// explode
m_iIndex=0;
while (m_iIndex<4) {
// spawn effect
CPlacement3D plExplosion;
plExplosion.pl_PositionVector = FLOAT3D(FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f, FRnd()*2.0f);
plExplosion.RelativeToAbsolute(GetPlacement());
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_GRENADE;
eSpawnEffect.vStretch = FLOAT3D(1,1,1);
CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT);
penExplosion->Initialize(eSpawnEffect);
// damage
FLOAT3D vSource;
GetEntityInfoPosition(this, eiCyborgBike.vTargetCenter, vSource);
InflictRangeDamage(this, DMT_EXPLOSION, 15.0f, vSource, 4.0f, 8.0f);
// next explosion
autowait(0.1f + FRnd()/5);
m_iIndex++;
}
// cease to exist
Destroy();
return;
};
// dummy main
Main(ECyborgBike ecb) {
m_fSpeed = ecb.fSpeed;
// declare yourself as a model
InitAsModel();
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetPhysicsFlags(EPF_MODEL_FLYING);
en_fDensity = 5000.0f;
SetHealth(50.0f);
// set your appearance
SetComponents(this, *GetModelObject(), MODEL_BIKE, TEXTURE_BIKE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0);
ModelChangeNotify();
jump MainLoop();
return;
};
};

View File

@ -0,0 +1,73 @@
229
%{
#include "Entities/StdH/StdH.h"
%}
class CDamager: CRationalEntity {
name "Damager";
thumbnail "Thumbnails\\Damager.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Damager",
2 CTString m_strDescription = "",
3 enum DamageType m_dmtType "Type" 'Y' = DMT_ABYSS, // type of damage
4 FLOAT m_fAmmount "Ammount" 'A' = 1000.0f, // ammount of damage
5 CEntityPointer m_penToDamage "Entity to Damage" 'E', // entity to damage, NULL to damage the triggerer
6 BOOL m_bDamageFromTriggerer "DamageFromTriggerer" 'S' = FALSE, // make the triggerer inflictor of the damage
components:
1 model MODEL_TELEPORT "Models\\Editor\\Copier.mdl",
2 texture TEXTURE_TELEPORT "Models\\Editor\\Copier.tex",
functions:
const CTString &GetDescription(void) const {
return m_strDescription;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_TELEPORT);
SetModelMainTexture(TEXTURE_TELEPORT);
((CTString&)m_strDescription).PrintF("%s:%g",
DamageType_enum.NameForValue(INDEX(m_dmtType)), m_fAmmount);
while (TRUE) {
// wait to someone trigger you and then damage it
wait() {
on (ETrigger eTrigger) : {
CEntity *penInflictor = this;
if (m_bDamageFromTriggerer) {
penInflictor = eTrigger.penCaused;
}
if (m_penToDamage!=NULL) {
InflictDirectDamage(m_penToDamage, penInflictor,
m_dmtType, m_fAmmount,
m_penToDamage->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0));
} else if (eTrigger.penCaused!=NULL) {
InflictDirectDamage(eTrigger.penCaused, penInflictor,
m_dmtType, m_fAmmount,
eTrigger.penCaused->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0));
}
stop;
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
};

276
Sources/Entities/Debris.es Normal file
View File

@ -0,0 +1,276 @@
602
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/BasicEffects";
enum DebrisParticlesType {
0 DPT_NONE "", // no particles
1 DPT_BLOODTRAIL "", // blood
2 DPR_SMOKETRAIL "", // smoke
3 DPR_SPARKS "", // sparks (for robots)
4 DPR_FLYINGTRAIL "", // just flying object
};
// input parameter for spawning a debris
event ESpawnDebris {
EntityInfoBodyType Eeibt, // body type
CModelData *pmd, // model for this debris
FLOAT fSize, // stretch factor
CTextureData *ptd, // texture for this debris
CTextureData *ptdRefl, // reflection texture
CTextureData *ptdSpec, // specular texture
CTextureData *ptdBump, // bump texture
INDEX iModelAnim, // animation for debris model
enum DebrisParticlesType dptParticles, // particles type
enum BasicEffectType betStain, // stain left when touching brushes
COLOR colDebris, // multiply color for debris
};
%{
%}
class CDebris: CMovableModelEntity {
name "Debris";
thumbnail "";
properties:
1 enum DebrisParticlesType m_dptParticles = DPT_NONE, // type of particles
2 INDEX m_iBodyType = 0, // body type of this debris
3 BOOL m_bFade = FALSE, // fade debris
4 FLOAT m_fFadeStartTime = 0.0f, // fade start time
5 FLOAT m_fFadeTime = 0.0f, // fade time
6 FLOAT3D m_fLastStainHitPoint = FLOAT3D(0,0,0), // last stain hit point
7 enum BasicEffectType m_betStain = BET_NONE, // type of stain left
8 INDEX m_ctLeftStains = 0, // count of stains already left
9 FLOAT m_tmStarted = 0.0f, // time when spawned
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return GetStdEntityInfo((EntityInfoBodyType)m_iBodyType);
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// cannot be damaged immediately after spawning
if ((_pTimer->CurrentTick()-m_tmStarted<1.0f)
||(dmtType==DMT_CANNONBALL_EXPLOSION) && (_pTimer->CurrentTick()-m_tmStarted<5.0f)) {
return;
}
CMovableModelEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
};
/************************************************************
* FADE OUT *
************************************************************/
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
if (m_bFade) {
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 FALSE;
};
/************************************************************
* EFFECTS *
************************************************************/
// leave a stain where hit
void LeaveStain(void)
{
// if no stains
if (m_betStain==BET_NONE) {
// do nothing
return;
}
// don't allow too many stains to be left
if (m_ctLeftStains>5) {
return;
}
ESpawnEffect ese;
FLOAT3D vPoint;
FLOATplane3D plPlaneNormal;
FLOAT fDistanceToEdge;
// on plane
if (GetNearestPolygon(vPoint, plPlaneNormal, fDistanceToEdge)) {
// away from last hit point and near to polygon
if ((m_fLastStainHitPoint-vPoint).Length()>3.0f &&
(vPoint-GetPlacement().pl_PositionVector).Length()<3.5f) {
m_fLastStainHitPoint = vPoint;
// stain
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = m_betStain;
ese.vNormal = FLOAT3D(plPlaneNormal);
GetNormalComponent( en_vCurrentTranslationAbsolute, plPlaneNormal, ese.vDirection);
FLOAT fLength = ese.vDirection.Length() / 7.5f;
fLength = Clamp( fLength, 1.0f, 15.0f);
ese.vStretch = FLOAT3D( 1.0f, fLength*1.0f, 1.0f);
SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f*(FRnd()+0.5f), ANGLE3D(0, 0, 0)), ese);
m_ctLeftStains++;
}
}
};
// spawn effect
void SpawnEffect(const CPlacement3D &plEffect, const class ESpawnEffect &eSpawnEffect)
{
CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT);
penEffect->Initialize(eSpawnEffect);
};
// particles
void RenderParticles(void)
{
// if going too slow
if (en_vCurrentTranslationAbsolute.Length()<0.1f) {
// don't render particles
return;
}
switch(m_dptParticles) {
case DPT_BLOODTRAIL: {
Particles_BloodTrail( this);
} break;
case DPR_SMOKETRAIL: {
Particles_GrenadeTrail( this);
} break;
case DPR_SPARKS: {
Particles_ColoredStarsTrail( this);
} break;
case DPR_FLYINGTRAIL:{
//Particles_WhiteLineTrail( this);
Particles_BombTrail( this);
} break;
default: ASSERT(FALSE);
case DPT_NONE:
return;
}
};
// explode
void Explode(void)
{
// spawn explosion
CPlacement3D plExplosion = GetPlacement();
CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT);
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_BOMB;
eSpawnEffect.vStretch = FLOAT3D(0.3f,0.3f,0.3f);
penExplosion->Initialize(eSpawnEffect);
}
/************************************************************
* MAIN *
************************************************************/
procedures:
Main(ESpawnDebris eSpawn)
{
InitAsModel();
SetPhysicsFlags(EPF_MODEL_BOUNCING|EPF_CANFADESPINNING);
SetCollisionFlags(ECF_DEBRIS);
SetFlags(GetFlags() | ENF_SEETHROUGH);
SetHealth(25.0f);
en_fBounceDampNormal = 0.15f;
en_fBounceDampParallel = 0.5f;
en_fJumpControlMultiplier = 0.0f;
// set density
if (eSpawn.Eeibt==EIBT_ICE) {
en_fDensity = 500.0f;
} else if (eSpawn.Eeibt==EIBT_WOOD) {
en_fDensity = 500.0f;
} else if (eSpawn.Eeibt==EIBT_FLESH) {
en_fDensity = 5000.0f;
en_fBounceDampNormal = 0.25f;
en_fBounceDampParallel = 0.75f;
} else if (TRUE) {
en_fDensity = 5000.0f;
}
// set appearance
m_dptParticles = eSpawn.dptParticles,
m_betStain = eSpawn.betStain;
m_iBodyType = (INDEX)eSpawn.Eeibt;
GetModelObject()->SetData(eSpawn.pmd);
GetModelObject()->mo_toTexture.SetData(eSpawn.ptd);
GetModelObject()->mo_toReflection.SetData(eSpawn.ptdRefl);
GetModelObject()->mo_toSpecular.SetData(eSpawn.ptdSpec);
GetModelObject()->mo_toBump.SetData(eSpawn.ptdBump);
GetModelObject()->PlayAnim(eSpawn.iModelAnim, AOF_LOOPING);
GetModelObject()->mo_Stretch = FLOAT3D( eSpawn.fSize, eSpawn.fSize, eSpawn.fSize);
// adjust color
GetModelObject()->mo_colBlendColor = eSpawn.colDebris|CT_OPAQUE;
ModelChangeNotify();
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
if (fEntitySize>0.5f) {
SetCollisionFlags(ECF_MODEL);
}
en_fCollisionSpeedLimit+=ClampDn(0.0f, fEntitySize*10.0f);
m_bFade = FALSE;
m_fLastStainHitPoint = FLOAT3D(32000.0f, 32000.0f, 32000.0f);
m_ctLeftStains = 0;
m_tmStarted = _pTimer->CurrentTick();
// wait some time
wait(FRnd()*2.0f + 3.0f) {
on (EBegin) : { resume; }
// if touched something
on (ETouch etouch) : {
// if it is brush
if (etouch.penOther->GetRenderType()==RT_BRUSH) {
// maybe leave stain
LeaveStain();
// if robot
if (m_iBodyType==EIBT_ROBOT) {
// explode
Explode();
SendEvent(EDeath());
resume;
}
}
resume;
}
on (EDeath) : { Destroy(); return; }
on (ETimer) : { stop; }
}
// fade away
SetCollisionFlags(ECF_DEBRIS);
m_fFadeStartTime = _pTimer->CurrentTick();
m_fFadeTime = 5.0f;
m_bFade = TRUE;
autowait(m_fFadeTime);
// cease to exist
Destroy();
return;
}
};

View File

@ -0,0 +1,415 @@
107
%{
#include "Entities/StdH/StdH.h"
#include "Entities/Effector.h"
#include "Entities/MovingBrush.h"
%}
uses "Entities/Devil";
uses "Entities/Debris";
uses "Entities/GradientMarker";
uses "Entities/Effector";
%{
struct DebrisInfo {
ULONG ulModelID;
ULONG ulTextureID;
FLOAT vOffset[3];
};
static struct DebrisInfo _ObeliskDebrisInfo[] =
{
{ MODEL_OBELISK01, TEXTURE_OBELISK, 0.0f, 114.4989f, 0.0f},
{ MODEL_OBELISK02, TEXTURE_OBELISK, 0.035f, 106.8628f, 0.0f},
{ MODEL_OBELISK03, TEXTURE_OBELISK, 0.0f, 98.628f, 0.0f},
{ MODEL_OBELISK04, TEXTURE_OBELISK, 0.0f, 90.4996f, 0.0f},
{ MODEL_OBELISK05, TEXTURE_OBELISK, 0.0f, 82.174f, 0.0f},
{ MODEL_OBELISK06, TEXTURE_OBELISK, 0.0f, 71.0425f, 0.0f},
{ MODEL_OBELISK07, TEXTURE_OBELISK, 0.0f, 59.2f, 0.0f},
{ MODEL_OBELISK08, TEXTURE_OBELISK, 0.0f, 46.65f, 0.0f},
{ MODEL_OBELISK09, TEXTURE_OBELISK, 0.0f, 36.6f, 0.0f},
};
static struct DebrisInfo _PylonDebrisInfo[] =
{
{ MODEL_PYLON01, TEXTURE_PYLON, -17.3379f, 55.92f, 0},
{ MODEL_PYLON02, TEXTURE_PYLON, -10.525f, 58.045f, 0},
{ MODEL_PYLON03, TEXTURE_PYLON, -17.66f, 42.32f, 0},
{ MODEL_PYLON04, TEXTURE_PYLON, -0.815000f, 54.69f, 0 },
{ MODEL_PYLON05, TEXTURE_PYLON, 14.795f, 51.65f, 0},
{ MODEL_PYLON06, TEXTURE_PYLON, 0.02f, 36.18f, 0},
{ MODEL_PYLON07, TEXTURE_PYLON, -10.289f, 33.982f, 0},
{ MODEL_PYLON08, TEXTURE_PYLON, -22.9152f, 28.6205f, 0},
{ MODEL_PYLON09, TEXTURE_PYLON, 21.932f, 47.2453f, 0},
};
%}
class CDestroyableArchitecture: CMovableBrushEntity {
name "DestroyableArchitecture";
thumbnail "Thumbnails\\DestroyableArchitecture.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "DestroyableArchitecture", // name
2 FLOAT m_fHealth "Health" 'H' = -1.0f, // health
3 enum EffectorEffectType m_etType "Type" 'Y' = ET_DESTROY_OBELISK, // name
4 FLOAT3D m_vDamageDir = FLOAT3D(0,0,0), // direction of damage
5 FLOAT m_fStretch "Stretch" 'S' = 1.0f, // debris stretch
6 CEntityPointer m_penGradient "Gradient" 'R',
10 COLOR m_colDebrises "Color of debrises" = C_WHITE,
11 INDEX m_ctDebrises "Debris count" = 12,
12 FLOAT m_fCandyEffect "Debris blow power" = 0.0f,
13 FLOAT m_fCubeFactor "Cube factor" = 1.0f,
14 BOOL m_bBlowupByDamager "Blowup by Damager" = FALSE, // if only damager can destroy brush
components:
// ************** DEBRIS PARTS **************
10 texture TEXTURE_OBELISK "Models\\CutSequences\\Obelisk\\Obelisk.tex",
11 model MODEL_OBELISK01 "Models\\CutSequences\\Obelisk\\Part01.mdl",
12 model MODEL_OBELISK02 "Models\\CutSequences\\Obelisk\\Part02.mdl",
13 model MODEL_OBELISK03 "Models\\CutSequences\\Obelisk\\Part03.mdl",
14 model MODEL_OBELISK04 "Models\\CutSequences\\Obelisk\\Part04.mdl",
15 model MODEL_OBELISK05 "Models\\CutSequences\\Obelisk\\Part05.mdl",
16 model MODEL_OBELISK06 "Models\\CutSequences\\Obelisk\\Part06.mdl",
17 model MODEL_OBELISK07 "Models\\CutSequences\\Obelisk\\Part07.mdl",
18 model MODEL_OBELISK08 "Models\\CutSequences\\Obelisk\\Part08.mdl",
19 model MODEL_OBELISK09 "Models\\CutSequences\\Obelisk\\Part09.mdl",
20 texture TEXTURE_PYLON "Models\\CutSequences\\Pylon\\Pylon.tex",
21 model MODEL_PYLON01 "Models\\CutSequences\\Pylon\\Part01.mdl",
22 model MODEL_PYLON02 "Models\\CutSequences\\Pylon\\Part02.mdl",
23 model MODEL_PYLON03 "Models\\CutSequences\\Pylon\\Part03.mdl",
24 model MODEL_PYLON04 "Models\\CutSequences\\Pylon\\Part04.mdl",
25 model MODEL_PYLON05 "Models\\CutSequences\\Pylon\\Part05.mdl",
26 model MODEL_PYLON06 "Models\\CutSequences\\Pylon\\Part06.mdl",
27 model MODEL_PYLON07 "Models\\CutSequences\\Pylon\\Part07.mdl",
28 model MODEL_PYLON08 "Models\\CutSequences\\Pylon\\Part08.mdl",
29 model MODEL_PYLON09 "Models\\CutSequences\\Pylon\\Part09.mdl",
// ************** NEEDED CLASSES **************
30 class CLASS_DEBRIS "Classes\\Debris.ecl",
31 class CLASS_EFFECTOR "Classes\\Effector.ecl",
// ************** STONE PARTS **************
32 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl",
33 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex",
functions:
void Precache(void)
{
PrecacheClass (CLASS_DEBRIS);
PrecacheModel (MODEL_STONE);
PrecacheTexture (TEXTURE_STONE);
// precache acording to destroying architecture
switch( m_etType)
{
case ET_DESTROY_OBELISK:
PrecacheClass (CLASS_EFFECTOR,ET_DESTROY_OBELISK);
PrecacheTexture (TEXTURE_OBELISK);
PrecacheModel (MODEL_OBELISK01);
PrecacheModel (MODEL_OBELISK02);
PrecacheModel (MODEL_OBELISK03);
PrecacheModel (MODEL_OBELISK04);
PrecacheModel (MODEL_OBELISK05);
PrecacheModel (MODEL_OBELISK06);
PrecacheModel (MODEL_OBELISK07);
PrecacheModel (MODEL_OBELISK08);
PrecacheModel (MODEL_OBELISK09);
break;
case ET_DESTROY_PYLON:
PrecacheClass (CLASS_EFFECTOR,ET_DESTROY_PYLON);
PrecacheTexture (TEXTURE_PYLON);
PrecacheModel (MODEL_PYLON01);
PrecacheModel (MODEL_PYLON02);
PrecacheModel (MODEL_PYLON03);
PrecacheModel (MODEL_PYLON04);
PrecacheModel (MODEL_PYLON05);
PrecacheModel (MODEL_PYLON06);
PrecacheModel (MODEL_PYLON07);
PrecacheModel (MODEL_PYLON08);
PrecacheModel (MODEL_PYLON09);
break;
}
}
// Validate offered target for one property
BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget)
{
if(penTarget==NULL)
{
return FALSE;
}
// if gradient marker
if( slPropertyOffset==offsetof(CDestroyableArchitecture, m_penGradient) )
{
return (IsDerivedFromClass(penTarget, "Gradient Marker"));
}
return CEntity::IsTargetValid(slPropertyOffset, penTarget);
}
/* Get gradient type name, return empty string if not used. */
const CTString &GetGradientName(INDEX iGradient)
{
static const CTString strDummyName("");
static const CTString strMarkerUnused("Marker not set");
if (iGradient==1)
{
CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient;
if (pgm != NULL) {
return pgm->GetGradientName();
} else {
return strMarkerUnused;
}
}
return strDummyName;
}
/* Uncache shadows for given gradient */
void UncacheShadowsForGradient(class CGradientMarker *penDiscard)
{
CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient;
if(pgm == penDiscard)
{
CEntity::UncacheShadowsForGradient(1);
}
}
/* Get gradient, return FALSE for none. */
BOOL GetGradient(INDEX iGradient, class CGradientParameters &fpGradient)
{
if ( iGradient==1)
{
CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient;
if (pgm != NULL) {
return pgm->GetGradient(0, fpGradient);
}
}
return FALSE;
}
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// if not destroyable
if(m_fHealth<0) {
// ignore damages
return;
}
if(m_bBlowupByDamager)
{
if( dmtType == DMT_DAMAGER)
{
CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
}
else
{
// react only on explosions
if( (dmtType == DMT_EXPLOSION) ||
(dmtType == DMT_PROJECTILE) ||
(dmtType == DMT_CANNONBALL) )
{
CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
}
}
void DestroyObelisk()
{
for( INDEX iDebris=0; iDebris<ARRAYCOUNT(_ObeliskDebrisInfo); iDebris++)
{
DebrisInfo &di = _ObeliskDebrisInfo[iDebris];
FLOAT3D vOffset = FLOAT3D( di.vOffset[0], di.vOffset[1], di.vOffset[2])*m_fStretch;
FLOAT3D vPos = GetPlacement().pl_PositionVector+vOffset;
CEntityPointer penDebris = GetWorld()->CreateEntity_t(
CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl"));
// prepare parameters
ESpawnDebris eSpawn;
eSpawn.colDebris = C_WHITE|CT_OPAQUE;
eSpawn.Eeibt = EIBT_ROCK;
eSpawn.dptParticles = DPT_NONE;
eSpawn.betStain = BET_NONE;
eSpawn.pmd = GetModelDataForComponent(di.ulModelID);
eSpawn.ptd = GetTextureDataForComponent(di.ulTextureID);
eSpawn.ptdRefl = NULL;
eSpawn.ptdSpec = NULL;
eSpawn.ptdBump = NULL;
eSpawn.iModelAnim = 0;
eSpawn.fSize = m_fStretch;
// initialize it
penDebris->Initialize(eSpawn);
// speed it up
FLOAT fHeightRatio = di.vOffset[1]*m_fStretch/120.0f;
FLOAT3D vSpeed = FLOAT3D( FRnd()-0.5f, 0.0f, FRnd()-0.5f)*(1.0f-fHeightRatio)*160.0f;
FLOAT3D vRot = FLOAT3D( FRnd()-0.5f, (FRnd()-0.5f)*(1.0f-fHeightRatio), FRnd()-0.5f)*200.0f;
/*
vSpeed = FLOAT3D( 0,0,0);
vRot = FLOAT3D( 0,0,0);*/
((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vSpeed, NULL);
((CMovableEntity&)*penDebris).SetDesiredRotation( vRot);
}
// notify children
FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) {
iten->SendEvent( EBrushDestroyed());
}
m_fHealth = -1;
ForceFullStop();
SetDefaultProperties();
CPlacement3D plObelisk = GetPlacement();
// notify engine to kickstart entities that are cached in stationary position,
// before we turn off, so they can fall
NotifyCollisionChanged();
SetFlags( GetFlags()|ENF_HIDDEN);
SetCollisionFlags(ECF_IMMATERIAL);
// spawn spray spray
CEntity *penEffector = CreateEntity( plObelisk, CLASS_EFFECTOR);
// set spawn parameters
ESpawnEffector eSpawnEffector;
eSpawnEffector.tmLifeTime = 6.0f;
eSpawnEffector.eetType = ET_DESTROY_OBELISK;
// initialize spray
penEffector->Initialize( eSpawnEffector);
}
void DestroyPylon()
{
for( INDEX iDebris=0; iDebris<ARRAYCOUNT(_PylonDebrisInfo); iDebris++)
{
DebrisInfo &di = _PylonDebrisInfo[iDebris];
FLOAT3D vOffset = FLOAT3D( di.vOffset[0], di.vOffset[1], di.vOffset[2])*m_fStretch;
FLOAT3D vPos = GetPlacement().pl_PositionVector+vOffset;
CEntityPointer penDebris = GetWorld()->CreateEntity_t(
CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl"));
// prepare parameters
ESpawnDebris eSpawn;
eSpawn.colDebris = C_WHITE|CT_OPAQUE;
eSpawn.Eeibt = EIBT_ROCK;
eSpawn.dptParticles = DPT_NONE;
eSpawn.betStain = BET_NONE;
eSpawn.pmd = GetModelDataForComponent(di.ulModelID);
eSpawn.ptd = GetTextureDataForComponent(di.ulTextureID);
eSpawn.ptdRefl = NULL;
eSpawn.ptdSpec = NULL;
eSpawn.ptdBump = NULL;
eSpawn.iModelAnim = 0;
eSpawn.fSize = m_fStretch;
// initialize it
penDebris->Initialize(eSpawn);
// speed it up
FLOAT fHeightRatio = di.vOffset[1]*m_fStretch/120.0f;
FLOAT3D vSpeed = (m_vDamageDir*2.0f+FLOAT3D( FRnd()-0.5f, 0.0f, FRnd()))*fHeightRatio*160.0f;
FLOAT3D vRot = FLOAT3D( FRnd()-0.5f, (FRnd()-0.5f)*fHeightRatio, FRnd()-0.5f)*300.0f;
((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vSpeed, NULL);
((CMovableEntity&)*penDebris).SetDesiredRotation( vRot);
}
// notify children
FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) {
iten->SendEvent( EBrushDestroyed());
}
m_fHealth = -1;
CPlacement3D plObelisk = GetPlacement();
// spawn spray spray
CEntity *penEffector = CreateEntity( plObelisk, CLASS_EFFECTOR);
// set spawn parameters
ESpawnEffector eSpawnEffector;
eSpawnEffector.eetType = ET_DESTROY_PYLON;
eSpawnEffector.tmLifeTime = 6.0f;
eSpawnEffector.vDamageDir = m_vDamageDir;
// initialize spray
penEffector->Initialize( eSpawnEffector);
ForceFullStop();
SetDefaultProperties();
// notify engine to kickstart entities that are cached in stationary position,
// before we turn off, so they can fall
NotifyCollisionChanged();
SetFlags( GetFlags()|ENF_HIDDEN);
SetCollisionFlags(ECF_IMMATERIAL);
}
procedures:
Main() {
// declare yourself as a brush
InitAsBrush();
SetPhysicsFlags(EPF_BRUSH_MOVING);
SetCollisionFlags(ECF_BRUSH);
// non-zoning brush
SetFlags(GetFlags()&~ENF_ZONING);
SetHealth(m_fHealth);
// start moving
wait() {
on (EBegin) : {
resume;
}
on (EBrushDestroyedByDevil ebdbd) :
{
m_vDamageDir = ebdbd.vDamageDir;
switch( m_etType)
{
case ET_DESTROY_OBELISK:
DestroyObelisk();
break;
case ET_DESTROY_PYLON:
DestroyPylon();
break;
}
stop;
}
on (EDeath eDeath) : {
// get your size
FLOATaabbox3D box;
GetSize(box);
if( m_ctDebrises<=0)
{
m_ctDebrises=1;
}
FLOAT fEntitySize = pow(box.Size()(1)*box.Size()(2)*box.Size()(3)/m_ctDebrises, 1.0f/3.0f)*m_fCubeFactor;
Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(1.0f,2.0f,3.0f),
FLOAT3D(0,0,0), 1.0f+m_fCandyEffect/2.0f, m_fCandyEffect, m_colDebrises);
for(INDEX iDebris = 0; iDebris<m_ctDebrises; iDebris++) {
Debris_Spawn(this, this, MODEL_STONE, TEXTURE_STONE, 0, 0, 0, IRnd()%4, 1.0f,
FLOAT3D(FRnd()*0.8f+0.1f, FRnd()*0.8f+0.1f, FRnd()*0.8f+0.1f));
}
// notify children
FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) {
iten->SendEvent( EBrushDestroyed());
}
m_fHealth = -1;
ForceFullStop();
SetDefaultProperties();
// notify engine to kickstart entities that are cached in stationary position,
// before we turn off, so they can fall
NotifyCollisionChanged();
SetFlags( GetFlags()|ENF_HIDDEN);
SetCollisionFlags(ECF_IMMATERIAL);
// for each child of this entity
{FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) {
// send it destruction event
itenChild->SendEvent(ERangeModelDestruction());
}}
stop;
}
on (EReturn) :
{
stop;
}
}
return;
}
};

2415
Sources/Entities/Devil.es Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,155 @@
338
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
uses "Entities/Devil";
enum DevilActionType {
0 DAT_NONE "None",
1 DAT_WALK "Walk",
2 DAT_RISE "Rise",
3 DAT_ROAR "Roar",
4 DAT_PUNCH_LEFT "Punch left - obsolete",
5 DAT_PUNCH_RIGHT "Punch right - obsolete",
6 DAT_HIT_GROUND "Hit ground",
7 DAT_JUMP "Jump",
8 DAT_WAIT "Wait",
9 DAT_STOP_DESTROYING "Stop destroying",
10 DAT_NEXT_ACTION "Next action",
11 DAT_GRAB_LOWER_WEAPONS "Grab lower weapons",
12 DAT_STOP_MOVING "Stop moving",
13 DAT_JUMP_INTO_PYRAMID "Jump into pyramid",
14 DAT_SMASH_LEFT "Smash left - obsolete",
15 DAT_SMASH_RIGHT "Smash right - obsolete",
16 DAT_PUNCH "Punch",
17 DAT_SMASH "Smash",
18 DAT_FORCE_ATTACK_RADIUS "Force attack radius",
19 DAT_TELEPORT_INTO_PYRAMID "Teleport into pyramid",
20 DAT_DECREASE_ATTACK_RADIUS "Decrease attack radius",
};
class CDevilMarker: CMarker {
name "Devil Marker";
thumbnail "Thumbnails\\EnemyMarker.tbn";
properties:
1 enum DevilActionType m_datType "Action" 'A' = DAT_NONE,
4 INDEX m_iWaitIdles "Wait idles" 'W' = 2,
5 CEntityPointer m_penDevil "Devil" 'D',
6 CEntityPointer m_penTrigger "Trigger" 'G',
7 CEntityPointer m_penToDestroy1 "Destroy target 1" 'E',
8 CEntityPointer m_penToDestroy2 "Destroy target 2" 'R',
9 RANGE m_fAttackRadius "Attack radius" 'S' = 100.0f,
components:
1 model MODEL_MARKER "Models\\Editor\\EnemyMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\DevilMarker.tex"
functions:
void SetDefaultName(void)
{
m_strName = DevilActionType_enum.NameForValue(INDEX(m_datType));
}
const CTString &GetDescription(void) const {
CTString strAction = DevilActionType_enum.NameForValue(INDEX(m_datType));
if (m_penTarget==NULL) {
((CTString&)m_strDescription).PrintF("%s (%s)-><none>",(const char*) m_strName,(const char*) strAction);
} else {
((CTString&)m_strDescription).PrintF("%s (%s)->%s",(const char*) m_strName,(const char*) strAction,
(const char*) m_penTarget->GetName());
}
return m_strDescription;
}
/* Check if entity is moved on a route set up by its targets. */
BOOL MovesByTargetedRoute(CTString &strTargetProperty) const {
strTargetProperty = "Target";
return TRUE;
};
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const {
fnmMarkerClass = CTFILENAME("Classes\\DevilMarker.ecl");
strTargetProperty = "Target";
return TRUE;
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
if (ee.ee_slEvent==EVENTCODE_ETrigger)
{
if(m_datType==DAT_NEXT_ACTION && m_penDevil!=NULL && m_penTarget!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_FORCE_ACTION;
eDevilCommand.penForcedAction = m_penTarget;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_GRAB_LOWER_WEAPONS && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_GRAB_LOWER_WEAPONS;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_STOP_MOVING && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_STOP_MOVING;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_JUMP_INTO_PYRAMID && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_JUMP_INTO_PYRAMID;
eDevilCommand.penForcedAction = this;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_TELEPORT_INTO_PYRAMID && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_TELEPORT_INTO_PYRAMID;
eDevilCommand.penForcedAction = this;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_FORCE_ATTACK_RADIUS && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_FORCE_ATTACK_RADIUS;
eDevilCommand.fAttackRadius = m_fAttackRadius;
eDevilCommand.vCenterOfAttack = GetPlacement().pl_PositionVector;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
else if(m_datType==DAT_DECREASE_ATTACK_RADIUS && m_penDevil!=NULL)
{
EDevilCommand eDevilCommand;
eDevilCommand.dctType = DC_DECREASE_ATTACK_RADIUS;
m_penDevil->SendEvent(eDevilCommand);
return TRUE;
}
}
return FALSE;
}
procedures:
Main() {
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
SetDefaultName();
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
return;
}
};

View File

@ -0,0 +1,270 @@
511
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/BasicEffects";
uses "Entities/Light";
// input parameter for launching the projectile
event EDevilProjectile {
CEntityPointer penLauncher, // who launched it
CEntityPointer penTarget, // target entity
};
%{
#define FLY_TIME 15.0f
#define ROTATE_SPEED 200.0f
#define MOVING_SPEED 30.0f
#define MOVING_FREQUENCY 0.1f
%}
class CDevilProjectile : CMovableModelEntity {
name "Devil projectile";
thumbnail "";
properties:
1 CEntityPointer m_penLauncher, // who lanuched it
2 CEntityPointer m_penTarget, // target entity
10 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored
11 FLOAT m_fStartTime = 0.0f, // start time when launched
12 FLOAT3D m_vDesiredAngle = FLOAT3D(0,0,0),
13 BOOL m_bFly = FALSE,
20 CSoundObject m_soEffect, // sound channel
{
CLightSource m_lsLightSource;
}
components:
1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
2 class CLASS_LIGHT "Classes\\Light.ecl",
// ********* PLAYER ROCKET *********
10 model MODEL_FLARE "Models\\Enemies\\Devil\\Flare.mdl",
11 texture TEXTURE_FLARE "Models\\Enemies\\Devil\\12.tex",
functions:
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CMovableModelEntity::Read_t(istr);
// setup light source
SetupLightSource();
};
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
if (!IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
};
// Setup light source
void SetupLightSource(void)
{
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC;
lsNew.ls_rHotSpot = 0.0f;
lsNew.ls_colColor = RGBToColor(0, 128, 128);
lsNew.ls_rFallOff = 5.0f;
lsNew.ls_plftLensFlare = NULL;
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = NULL;
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
};
/************************************************************
* 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*MOVING_FREQUENCY) {
// start turning left
aRotation = -ROTATE_SPEED;
// if desired position is right
} else if (aWantedHeadingRelative > ROTATE_SPEED*MOVING_FREQUENCY) {
// start turning right
aRotation = +ROTATE_SPEED;
// if desired position is more-less ahead
} else {
aRotation = aWantedHeadingRelative/MOVING_FREQUENCY;
}
};
// calculate angle from position
void CalcAngleFromPosition() {
// target enemy body
FLOAT3D vTarget;
/* EntityInfo *peiTarget = (EntityInfo*) (m_penTarget->GetEntityInfo());
GetEntityInfoPosition(m_penTarget, peiTarget->vTargetCenter, vTarget);*/
vTarget = m_penTarget->GetPlacement().pl_PositionVector;
vTarget += FLOAT3D(m_penTarget->en_mRotation(1, 2),
m_penTarget->en_mRotation(2, 2),
m_penTarget->en_mRotation(3, 2)) * 2.0f;
// find relative orientation towards the desired position
m_vDesiredAngle = (vTarget - 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));
};
// fly move in direction
void FlyInDirection() {
RotateToAngle();
// target enemy body
FLOAT3D vTarget;
/* EntityInfo *peiTarget = (EntityInfo*) (m_penTarget->GetEntityInfo());
GetEntityInfoPosition(m_penTarget, peiTarget->vTargetCenter, vTarget);*/
vTarget = m_penTarget->GetPlacement().pl_PositionVector;
vTarget += FLOAT3D(m_penTarget->en_mRotation(1, 2),
m_penTarget->en_mRotation(2, 2),
m_penTarget->en_mRotation(3, 2)) * 2.0f;
// determine translation speed
FLOAT3D vTranslation = (vTarget - GetPlacement().pl_PositionVector) * !en_mRotation;
vTranslation(1) = 0.0f;
vTranslation.Normalize();
vTranslation *= MOVING_SPEED;
// start moving
SetDesiredTranslation(vTranslation);
};
// fly entity to desired position
void FlyToPosition() {
CalcAngleFromPosition();
FlyInDirection();
};
// 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));
};
/************************************************************
* C O M M O N F U N C T I O N S *
************************************************************/
void ProjectileTouch(CEntityPointer penHit) {
// direct damage
FLOAT3D vDirection;
AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection);
InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, 15.0f,
GetPlacement().pl_PositionVector, vDirection);
};
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
Fly(EVoid) {
// bounce loop
m_bFly = TRUE;
while(m_bFly && m_fStartTime+FLY_TIME > _pTimer->CurrentTick()) {
wait(0.1f) {
on (EBegin) : {
FlyToPosition();
resume;
}
on (EPass epass) : {
BOOL bHit;
// ignore launcher within 1 second
bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime;
// ignore twister
bHit &= !IsOfClass(epass.penOther, "Twister");
if (bHit) {
ProjectileTouch(epass.penOther);
m_bFly = FALSE;
stop;
}
resume;
}
on (ETouch etouch) : {
// clear time limit for launcher
m_fIgnoreTime = 0.0f;
resume;
}
on (ETimer) : { stop; }
}
}
return EEnd();
};
// --->>> MAIN
Main(EDevilProjectile eLaunch) {
// remember the initial parameters
ASSERT(eLaunch.penLauncher!=NULL);
ASSERT(eLaunch.penTarget!=NULL);
m_penLauncher = eLaunch.penLauncher;
m_penTarget = eLaunch.penTarget;
// set appearance
InitAsModel();
SetPhysicsFlags(EPF_PROJECTILE_FLYING);
SetCollisionFlags(ECF_PROJECTILE_MAGIC);
SetModel(MODEL_FLARE);
SetModelMainTexture(TEXTURE_FLARE);
// setup light source
SetupLightSource();
// remember lauching time
m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f;
// fly
m_fStartTime = _pTimer->CurrentTick();
autocall Fly() EEnd;
// cease to exist
Destroy();
return;
}
};

View File

@ -0,0 +1,334 @@
221
%{
#include "Entities/StdH/StdH.h"
#include <Engine/CurrentVersion.h>
%}
uses "Entities/KeyItem";
uses "Entities/Player";
enum DoorType {
0 DT_AUTO "Auto", // opens automatically
1 DT_TRIGGERED "Triggered", // opens when triggered
2 DT_LOCKED "Locked", // requires a key
3 DT_TRIGGEREDAUTO "Triggered Auto", // opens automatically after being triggered
};
class CDoorController : CRationalEntity {
name "DoorController";
thumbnail "Thumbnails\\DoorController.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "DoorController",
2 CTString m_strDescription = "",
3 CEntityPointer m_penTarget1 "Target1" 'T' COLOR(C_MAGENTA|0xFF),
4 CEntityPointer m_penTarget2 "Target2" COLOR(C_MAGENTA|0xFF),
5 FLOAT m_fWidth "Width" 'W' = 2.0f,
6 FLOAT m_fHeight "Height" 'H' = 3.0f,
7 BOOL m_bPlayersOnly "Players Only" 'P' = TRUE,
8 enum DoorType m_dtType "Type" 'Y' = DT_AUTO,
9 CTStringTrans m_strLockedMessage "Locked message" 'L' = "",
13 CEntityPointer m_penLockedTarget "Locked target" COLOR(C_dMAGENTA|0xFF), // target to trigger when locked
12 enum KeyItemType m_kitKey "Key" 'K' = KIT_ANKHWOOD, // key type (for locked door)
14 BOOL m_bTriggerOnAnything "Trigger on anything" = FALSE,
15 BOOL m_bActive "Active" 'A' = TRUE, // automatic door function can be activated/deactivated
10 BOOL m_bLocked = FALSE, // for lock/unlock door
11 CEntityPointer m_penCaused, // for trigger relaying
components:
1 model MODEL_DOORCONTROLLER "Models\\Editor\\DoorController.mdl",
2 texture TEXTURE_DOORCONTROLLER "Models\\Editor\\DoorController.tex",
functions:
CEntity *GetTarget(void) const { return m_penTarget1; };
const CTString &GetDescription(void) const {
if (m_penTarget1!=NULL && m_penTarget2!=NULL) {
((CTString&)m_strDescription).PrintF("->%s,%s",
(const char*) m_penTarget1->GetName(),(const char*) m_penTarget2->GetName());
} else if (m_penTarget1!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",
(const char*) m_penTarget1->GetName());
} else {
((CTString&)m_strDescription).PrintF("-><none>");
}
return m_strDescription;
}
// test if this door reacts on this entity
BOOL CanReactOnEntity(CEntity *pen)
{
if (pen==NULL) {
return FALSE;
}
// never react on non-live or dead entities
if (!(pen->GetFlags()&ENF_ALIVE)) {
return FALSE;
}
if (m_bPlayersOnly && !IsDerivedFromClass(pen, "Player")) {
return FALSE;
}
return TRUE;
}
// test if this door can be triggered by this entity
BOOL CanTriggerOnEntity(CEntity *pen)
{
return m_bTriggerOnAnything || CanReactOnEntity(pen);
}
void TriggerDoor(void)
{
if (m_penTarget1!=NULL) {
SendToTarget(m_penTarget1, EET_TRIGGER, m_penCaused);
}
if (m_penTarget2!=NULL) {
SendToTarget(m_penTarget2, EET_TRIGGER, m_penCaused);
}
}
// apply mirror and stretch to the entity
void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX)
{
// stretch its ranges
m_fWidth*=fStretch;
m_fHeight*=fStretch;
}
procedures:
// entry point for automatic functioning
DoorAuto()
{
// go into active or inactive state
if (m_bActive) {
jump DoorAutoActive();
} else {
jump DoorAutoInactive();
}
}
// automatic door active state
DoorAutoActive()
{
ASSERT(m_bActive);
while (TRUE) {
// wait
wait() {
// when someone enters
on (EPass ePass) : {
// if he can open the door
if (CanReactOnEntity(ePass.penOther)) {
// do it
m_penCaused = ePass.penOther;
TriggerDoor();
// this is a very ugly fix for cooperative not finishing in the demo level
// remove this when not needed any more!!!!
if(_SE_DEMO && GetSP()->sp_bCooperative && !GetSP()->sp_bSinglePlayer) {
if (m_strName=="Appear gold amon") {
CPlayer *penPlayer = (CPlayer*)&*ePass.penOther;
penPlayer->SetGameEnd();
}
}
resume;
}
resume;
}
// if door is deactivated
on (EDeactivate) : {
// go to inactive state
m_bActive = FALSE;
jump DoorAutoInactive();
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
// automatic door inactive state
DoorAutoInactive()
{
ASSERT(!m_bActive);
while (TRUE) {
// wait
wait() {
// if door is activated
on (EActivate) : {
// go to active state
m_bActive = TRUE;
jump DoorAutoActive();
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
// door when do not function anymore
DoorDummy()
{
wait() {
on (EBegin) : {
resume;
}
otherwise() : {
resume;
};
}
}
// door that wait to be triggered to open
DoorTriggered()
{
while (TRUE) {
// wait to someone enter
wait() {
on (EPass ePass) : {
if (CanReactOnEntity(ePass.penOther)) {
if (m_strLockedMessage!="") {
PrintCenterMessage(this, ePass.penOther, TranslateConst(m_strLockedMessage), 3.0f, MSS_INFO);
}
if (m_penLockedTarget!=NULL) {
SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther);
}
resume;
}
}
on (ETrigger eTrigger) : {
m_penCaused = eTrigger.penCaused;
TriggerDoor();
jump DoorDummy();
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
// door that need a key to be unlocked to open
DoorLocked()
{
while (TRUE) {
// wait to someone enter
wait() {
on (EPass ePass) : {
if (IsDerivedFromClass(ePass.penOther, "Player")) {
CPlayer *penPlayer = (CPlayer*)&*ePass.penOther;
// if he has the key
ULONG ulKey = (1<<INDEX(m_kitKey));
if (penPlayer->m_ulKeys&ulKey) {
// use the key
penPlayer->m_ulKeys&=~ulKey;
// open the dook
TriggerDoor();
/*
// tell the key bearer that the key was used
CTString strMsg;
strMsg.PrintF(TRANS("%s used"), GetKeyName(m_kitKey));
PrintCenterMessage(this, ePass.penOther, strMsg, 3.0f, MSS_INFO);
*/
// become automatic door
jump DoorAuto();
// if he has no key
} else {
if (m_penLockedTarget!=NULL) {
SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther);
}
}
resume;
}
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
// door that need to be triggered to start working automatically
DoorTriggeredAuto()
{
while (TRUE) {
// wait to be triggered
wait() {
on (ETrigger eTrigger) : {
// become auto door
jump DoorAuto();
}
on (EPass ePass) : {
if (CanReactOnEntity(ePass.penOther)) {
if (m_strLockedMessage!="") {
PrintCenterMessage(this, ePass.penOther, TranslateConst(m_strLockedMessage), 3.0f, MSS_INFO);
}
if (m_penLockedTarget!=NULL) {
SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther);
}
}
resume;
}
otherwise() : {
resume;
};
};
// wait a bit to recover
autowait(0.1f);
}
}
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_TOUCHMODEL);
// set appearance
GetModelObject()->StretchModel(FLOAT3D(m_fWidth, m_fHeight, m_fWidth));
SetModel(MODEL_DOORCONTROLLER);
SetModelMainTexture(TEXTURE_DOORCONTROLLER);
ModelChangeNotify();
// don't start in wed
autowait(0.1f);
// dispatch to aproppriate loop
switch(m_dtType) {
case DT_AUTO: {
jump DoorAuto();
} break;
case DT_TRIGGERED: {
jump DoorTriggered();
} break;
case DT_TRIGGEREDAUTO: {
jump DoorTriggeredAuto();
} break;
case DT_LOCKED: {
jump DoorLocked();
} break;
}
}
};

View File

@ -0,0 +1,616 @@
321
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/DragonMan/DragonMan.h"
%}
uses "Entities/EnemyFly";
uses "Entities/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();
};
};

View File

@ -0,0 +1,291 @@
611
%{
#include "Entities/StdH/StdH.h"
#include "Entities/Effector.h"
#include "Entities/BackgroundViewer.h"
#include "Entities/WorldSettingsController.h"
%}
uses "Entities/Marker";
enum EffectMarkerType {
0 EMT_NONE "None", // no FX
1 EMT_PLAYER_APPEAR "Player appear", // effect of player appearing
2 EMT_APPEARING_BIG_BLUE_FLARE "Appear big blue flare", // appear big blue flare
3 EMT_BLEND_MODELS "Blend two models", // blend between two models
4 EMT_DISAPPEAR_MODEL "Disappear model", // disappear model
5 EMT_APPEAR_MODEL "Appear model", // appear model
6 EMT_HIDE_ENTITY "Hide entity", // hide entity
7 EMT_SHOW_ENTITY "Show entity", // show entity
8 EMT_SHAKE_IT_BABY "Shake it baby", // earth quaker
9 EMT_APPEAR_DISAPPEAR "Appear or Disappear model", // appear/disappear model
};
class CEffectMarker: CMarker
{
name "Effect Marker";
thumbnail "Thumbnails\\EffectMarker.tbn";
properties:
1 enum EffectMarkerType m_emtType "Effect type" 'Y' = EMT_NONE, // type of effect
2 CEntityPointer m_penModel "FX Model" 'M', // model holder used in this effect
3 FLOAT m_tmEffectLife "FX Life time" 'L' = 10.0f, // life time of this effect
4 CEntityPointer m_penModel2 "FX Model 2" 'O', // second model holder used in this effect
5 CEntityPointer m_penEffector, // ptr to spawned effector
6 FLOAT m_fShakeFalloff "Shake fall off" = 250.0f, // ShakeFalloff
7 FLOAT m_fShakeFade "Shake fade" = 3.0f, // ShakeFade
8 FLOAT m_fShakeIntensityY "Shake intensity Y" = 0.1f, // ShakeIntensityY
9 FLOAT m_fShakeFrequencyY "Shake frequency Y" = 5.0f, // ShakeFrequencyY
10 FLOAT m_fShakeIntensityB "Shake intensity B" = 2.5f, // ShakeIntensityB
11 FLOAT m_fShakeFrequencyB "Shake frequency B" = 7.2f, // ShakeFrequencyB
12 FLOAT m_fShakeIntensityZ "Shake intensity Z" = 0.0f, // ShakeIntensityZ
13 FLOAT m_fShakeFrequencyZ "Shake frequency Z" = 5.0f, // ShakeFrequencyZ
components:
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex",
3 class CLASS_EFFECTOR "Classes\\Effector.ecl",
functions:
// Validate offered target for one property
BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget)
{
if(penTarget==NULL)
{
return FALSE;
}
// if should be modelobject
if( slPropertyOffset==offsetof(CEffectMarker, m_penModel) ||
slPropertyOffset==offsetof(CEffectMarker, m_penModel2) )
{
return IsOfClass(penTarget, "ModelHolder2");
}
return TRUE;
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
if (ee.ee_slEvent==EVENTCODE_ETrigger)
{
switch(m_emtType)
{
case EMT_SHAKE_IT_BABY:
{
// ---------- Apply shake
CWorldSettingsController *pwsc = NULL;
// obtain bcg viewer
CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer();
if( penBcgViewer != NULL)
{
pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController;
pwsc->m_tmShakeStarted = _pTimer->CurrentTick();
pwsc->m_vShakePos = GetPlacement().pl_PositionVector;
pwsc->m_fShakeFalloff = m_fShakeFalloff;
pwsc->m_fShakeFade = m_fShakeFade;
pwsc->m_fShakeIntensityZ = m_fShakeIntensityZ;
pwsc->m_tmShakeFrequencyZ = m_fShakeFrequencyZ;
pwsc->m_fShakeIntensityY = m_fShakeIntensityY;
pwsc->m_tmShakeFrequencyY = m_fShakeFrequencyY;
pwsc->m_fShakeIntensityB = m_fShakeIntensityB;
pwsc->m_tmShakeFrequencyB = m_fShakeFrequencyB;
}
break;
}
case EMT_HIDE_ENTITY:
{
if( m_penTarget!=NULL)
{
m_penTarget->SetFlags(m_penTarget->GetFlags()|ENF_HIDDEN);
}
break;
}
case EMT_SHOW_ENTITY:
{
if( m_penTarget!=NULL)
{
m_penTarget->SetFlags(m_penTarget->GetFlags()&~ENF_HIDDEN);
}
break;
}
case EMT_PLAYER_APPEAR:
if( m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2") )
{
CModelObject *pmo = m_penModel->GetModelObject();
if( pmo != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_PORTAL_LIGHTNING;
eSpawnFX.penModel = m_penModel;
penFX->Initialize( eSpawnFX);
}
}
break;
case EMT_APPEARING_BIG_BLUE_FLARE:
{
// spawn effect
CPlacement3D plFX= GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.fSize = 1.0f;
eSpawnFX.eetType = ET_SIZING_BIG_BLUE_FLARE;
penFX->Initialize( eSpawnFX);
break;
}
case EMT_BLEND_MODELS:
if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2") &&
m_penModel2!=NULL && IsOfClass(m_penModel2, "ModelHolder2") )
{
if( m_penEffector == NULL)
{
CModelObject *pmo1 = m_penModel->GetModelObject();
CModelObject *pmo2 = m_penModel2->GetModelObject();
if( pmo1 != NULL && pmo2 != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_MORPH_MODELS;
eSpawnFX.penModel = m_penModel;
eSpawnFX.penModel2 = m_penModel2;
penFX->Initialize( eSpawnFX);
m_penEffector = penFX;
}
}
else
{
m_penEffector->SendEvent(ETrigger());
}
}
break;
case EMT_DISAPPEAR_MODEL:
if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2"))
{
if( m_penEffector == NULL)
{
CModelObject *pmo = m_penModel->GetModelObject();
if( pmo != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_DISAPPEAR_MODEL;
eSpawnFX.penModel = m_penModel;
penFX->Initialize( eSpawnFX);
m_penEffector = penFX;
}
}
else
{
m_penEffector->SendEvent(ETrigger());
}
}
break;
case EMT_APPEAR_MODEL:
if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2"))
{
if( m_penEffector == NULL)
{
CModelObject *pmo = m_penModel->GetModelObject();
if( pmo != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_APPEAR_MODEL;
eSpawnFX.penModel = m_penModel;
penFX->Initialize( eSpawnFX);
m_penEffector = penFX;
}
}
else
{
m_penEffector->SendEvent(ETrigger());
}
}
break;
}
}
else if (ee.ee_slEvent==EVENTCODE_EActivate)
{
switch(m_emtType)
{
case EMT_APPEAR_DISAPPEAR:
if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2"))
{
CModelObject *pmo = m_penModel->GetModelObject();
if( pmo != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_APPEAR_MODEL_NOW;
eSpawnFX.penModel = m_penModel;
penFX->Initialize( eSpawnFX);
m_penEffector = penFX;
}
}
break;
}
}
else if (ee.ee_slEvent==EVENTCODE_EDeactivate)
{
switch(m_emtType)
{
case EMT_APPEAR_DISAPPEAR:
if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2"))
{
CModelObject *pmo = m_penModel->GetModelObject();
if( pmo != NULL)
{
// spawn effect
CPlacement3D plFX= m_penModel->GetPlacement();
CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR);
ESpawnEffector eSpawnFX;
eSpawnFX.tmLifeTime = m_tmEffectLife;
eSpawnFX.eetType = ET_DISAPPEAR_MODEL_NOW;
eSpawnFX.penModel = m_penModel;
penFX->Initialize( eSpawnFX);
m_penEffector = penFX;
}
}
break;
}
}
return FALSE;
}
procedures:
Main()
{
// init model
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// reset entity ptr
m_penEffector = NULL;
return;
}
};

View File

@ -0,0 +1,468 @@
608
%{
#include "Entities/StdH/StdH.h"
#include "Entities/Effector.h"
#include <Entities/BloodSpray.h>
%}
enum EffectorEffectType {
0 ET_NONE "None", // no particles
1 ET_DESTROY_OBELISK "Destroy obelisk", // effect of obelisk destroying
2 ET_DESTROY_PYLON "Destroy pylon", // effect of pylon destroying
3 ET_HIT_GROUND "Hit ground", // effect of hitting ground
4 ET_LIGHTNING "Lightning", // lightning effect
5 ET_SIZING_BIG_BLUE_FLARE "Sizing big blue flare", // sizing big blue flare with reflections effect
6 ET_SIZING_RING_FLARE "Sizing ring flare", // sizing ringed flare effect
7 ET_MOVING_RING "Moving ring", // moving ring effect
8 ET_PORTAL_LIGHTNING "Portal lightnings", // lightnings between portal vertices
9 ET_MORPH_MODELS "Morph two models", // morph wto models
10 ET_DISAPPEAR_MODEL "Disappear model", // disappear model
11 ET_APPEAR_MODEL "Appear model", // appear model
12 ET_DISAPPEAR_MODEL_NOW "Disappear model now", // disappear model now
13 ET_APPEAR_MODEL_NOW "Appear model now", // appear model now
};
// input parameter for spawning effector
event ESpawnEffector {
enum EffectorEffectType eetType, // type of particles
FLOAT3D vDamageDir, // direction of damage
FLOAT3D vDestination, // FX Destination
FLOAT tmLifeTime, // FX's life period
FLOAT fSize, // misc size
INDEX ctCount, // misc count
CEntityPointer penModel, // ptr to model object used in this effect
CEntityPointer penModel2, // ptr to second model object used in this effect
};
%{
void CEffector_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
switch ((EffectorEffectType)iUser)
{
case ET_MOVING_RING :
pdec->PrecacheModel(MODEL_POWER_RING);
pdec->PrecacheTexture(TEXTURE_POWER_RING);
break;
case ET_DESTROY_OBELISK :
case ET_DESTROY_PYLON :
case ET_HIT_GROUND :
case ET_LIGHTNING :
case ET_SIZING_BIG_BLUE_FLARE :
case ET_SIZING_RING_FLARE :
case ET_PORTAL_LIGHTNING :
case ET_MORPH_MODELS :
case ET_DISAPPEAR_MODEL :
case ET_APPEAR_MODEL :
case ET_DISAPPEAR_MODEL_NOW :
case ET_APPEAR_MODEL_NOW :
// no precaching needed
break;
default:
ASSERT(FALSE);
}
}
// array for model vertices in absolute space
CStaticStackArray<FLOAT3D> avModelFXVertices;
%}
class CEffector: CMovableModelEntity {
name "Effector";
thumbnail "";
features "ImplementsOnPrecache";
properties:
1 enum EffectorEffectType m_eetType = ET_NONE, // type of effect
2 FLOAT m_tmStarted = 0.0f, // time when spawned
3 FLOAT3D m_vDamageDir = FLOAT3D(0,0,0), // direction of damage
4 FLOAT3D m_vFXDestination = FLOAT3D(0,0,0), // FX destination
5 FLOAT m_tmLifeTime = 5.0f, // how long effect lives
6 FLOAT m_fSize = 1.0f, // effect's stretcher
8 INDEX m_ctCount = 0, // misc count
10 BOOL m_bLightSource = FALSE, // effect is also light source
11 CAnimObject m_aoLightAnimation, // light animation object
12 INDEX m_iLightAnimation = -1, // light animation index
13 BOOL m_bAlive = TRUE, // if effector is still alive
14 CEntityPointer m_penModel, // ptr to model object used in this effect
15 CEntityPointer m_penModel2, // ptr to second model object used in this effect
16 BOOL m_bWaitTrigger = FALSE, // if effect is activated using trigger
{
CLightSource m_lsLightSource;
}
components:
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex",
3 model MODEL_POWER_RING "Models\\CutSequences\\SpaceShip\\PowerRing.mdl",
4 texture TEXTURE_POWER_RING "Models\\CutSequences\\SpaceShip\\PowerRing.tex"
functions:
// calculate life ratio
FLOAT CalculateLifeRatio(FLOAT fFadeInRatio, FLOAT fFadeOutRatio)
{
TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted;
FLOAT fLifeRatio = CalculateRatio( tmDelta, 0, m_tmLifeTime, fFadeInRatio, fFadeOutRatio);
return fLifeRatio;
}
void AdjustMipFactor(FLOAT &fMipFactor)
{
if (m_eetType==ET_DISAPPEAR_MODEL || m_eetType==ET_DISAPPEAR_MODEL_NOW && m_penModel!=NULL)
{
CModelObject *pmo = m_penModel->GetModelObject();
TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted;
FLOAT fLifeRatio;
if( m_tmStarted == -1)
{
fLifeRatio = 1.0f;
}
else if( tmDelta>=m_tmLifeTime)
{
fLifeRatio = 0.0f;
}
else
{
fLifeRatio = CalculateLifeRatio(0.0f, 1.0f);
}
UBYTE ubAlpha = UBYTE(255.0f*fLifeRatio);
COLOR col = C_WHITE|ubAlpha;
pmo->mo_colBlendColor = col;
}
if (m_eetType==ET_APPEAR_MODEL || m_eetType==ET_APPEAR_MODEL_NOW && m_penModel!=NULL)
{
CModelObject *pmo = m_penModel->GetModelObject();
TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted;
FLOAT fLifeRatio;
if( m_tmStarted == -1)
{
fLifeRatio = 0.0f;
}
else if( tmDelta>=m_tmLifeTime)
{
fLifeRatio = 1.0f;
}
else
{
fLifeRatio = CalculateLifeRatio(1.0f, 0.0f);
}
UBYTE ubAlpha = UBYTE(255.0f*fLifeRatio);
COLOR col = C_WHITE|ubAlpha;
pmo->mo_colBlendColor = col;
}
if (m_eetType==ET_MORPH_MODELS && m_penModel!=NULL && m_penModel2!=NULL)
{
CModelObject *pmo1 = m_penModel->GetModelObject();
CModelObject *pmo2 = m_penModel2->GetModelObject();
TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted;
FLOAT fLifeRatio;
if( m_tmStarted == -1)
{
fLifeRatio = 0.0f;
}
else if( tmDelta>=m_tmLifeTime)
{
fLifeRatio = 1.0f;
}
else
{
fLifeRatio = CalculateLifeRatio(1.0f, 0.0f);
}
UBYTE ubAlpha1 = UBYTE(255.0f*(1-fLifeRatio));
UBYTE ubAlpha2 = 255-ubAlpha1;
COLOR col1 = C_WHITE|ubAlpha1;
COLOR col2 = C_WHITE|ubAlpha2;
pmo1->mo_colBlendColor = col1;
pmo2->mo_colBlendColor = col2;
}
}
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
if(m_eetType==ET_MOVING_RING)
{
FLOAT fLifeRatio = CalculateLifeRatio(0.2f, 0.1f);
FLOAT fT = _pTimer->CurrentTick()-m_tmStarted;
FLOAT fPulse = 1.0f;
UBYTE ub = UBYTE (255.0f*fPulse*fLifeRatio);
COLOR col = RGBAToColor(ub,ub,ub,ub);
GetModelObject()->mo_colBlendColor = col;
}
return FALSE;
}
void RenderMovingLightnings(void)
{
// calculate life ratio
FLOAT fLifeRatio = CalculateLifeRatio(0.1f, 0.1f);
// fill array with absolute vertices of entity's model and its attached models
m_penModel->GetModelVerticesAbsolute(avModelFXVertices, 0.05f, 0.0f);
const FLOATmatrix3D &m = m_penModel->GetRotationMatrix();
FLOAT3D vOrigin = m_penModel->GetPlacement().pl_PositionVector;
FLOAT fFXTime = 0.75f;
FLOAT fMaxHeight = 6.0f;
FLOAT fdh = 1.0f;
FLOAT tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted;
FLOAT fY0 = tmDelta;
for(FLOAT fT=tmDelta; fT>0; fT-=fFXTime)
{
FLOAT fY = fT*2.0f;
if( fY>fMaxHeight)
{
continue;
}
// calculate height ratio
FLOAT fHeightRatio = CalculateRatio( fY, 0, fMaxHeight, 0.1f, 0.0f);
FLOAT fMinY = 1e6f;
FLOAT fMinY2 = -1e6f;
INDEX iLower = -1;
INDEX iUpper = -1;
for( INDEX iVtx=0; iVtx<avModelFXVertices.Count(); iVtx++)
{
// get relative vertex coordinate
FLOAT3D v = (avModelFXVertices[iVtx]-vOrigin)*!m;
if( v(2)>fY && v(2)<fMinY && v(1)<0)
{
iLower = iVtx;
fMinY = v(2);
}
if( v(2)<=fY && v(2)>fMinY2 && v(1)<0)
{
iUpper = iVtx;
fMinY2 = v(2);
}
}
// if we found valid vertex
if( iLower!=-1 && iUpper!=-1)
{
FLOAT3D vRelHi = (avModelFXVertices[iUpper]-vOrigin)*!m;
FLOAT3D vRelLow = (avModelFXVertices[iLower]-vOrigin)*!m;
FLOAT fLerpFactor = (fY-vRelLow(2))/(vRelHi(2)-vRelLow(2));
FLOAT3D vRel = Lerp(vRelLow, vRelHi, fLerpFactor);
vRel(2) = fY;
FLOAT3D vAbs1 = vOrigin+vRel*m;
vRel(1)=-vRel(1);
FLOAT3D vAbs2 = vOrigin+vRel*m;
// render lightning
Particles_Ghostbuster( vAbs1, vAbs2, 16, 0.325f, fHeightRatio*fLifeRatio, 5.0f);
}
}
avModelFXVertices.Clear();
}
// particles
void RenderParticles(void)
{
// calculate ratio
FLOAT fRatio;
TIME tmNow = _pTimer->GetLerpedCurrentTick();
TIME tmDelta = tmNow - m_tmStarted;
FLOAT fLivingRatio = tmDelta/m_tmLifeTime;
if(fLivingRatio<0.25f) {
fRatio = Clamp( fLivingRatio/0.25f, 0.0f, 1.0f);
} else if(fLivingRatio>0.75f) {
fRatio = Clamp( (-fLivingRatio+1.0f)/0.25f, 0.0f, 1.0f);
} else {
fRatio = 1.0f;
}
switch( m_eetType)
{
case ET_DESTROY_OBELISK:
Particles_DestroyingObelisk( this, m_tmStarted);
break;
case ET_DESTROY_PYLON:
Particles_DestroyingPylon( this, m_vDamageDir, m_tmStarted);
break;
case ET_HIT_GROUND:
Particles_HitGround( this, m_tmStarted, m_fSize);
break;
case ET_LIGHTNING:
Particles_Ghostbuster(GetPlacement().pl_PositionVector, m_vFXDestination, m_ctCount, m_fSize, fRatio);
break;
case ET_PORTAL_LIGHTNING:
RenderMovingLightnings();
break;
}
};
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CMovableModelEntity::Read_t(istr);
// setup light source
if( m_bLightSource) {
SetupLightSource();
}
}
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
if( m_bLightSource && !IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
}
// Setup light source
void SetupLightSource(void)
{
if( m_iLightAnimation>=0)
{ // set light animation if available
try {
m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\Effector.ani"));
} catch (char *strError) {
WarningMessage(TRANS("Cannot load Animations\\Effector.ani: %s"), strError);
}
// play light animation
if (m_aoLightAnimation.GetData()!=NULL) {
m_aoLightAnimation.PlayAnim(m_iLightAnimation, 0);
}
}
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_LENSFLAREONLY;
lsNew.ls_rHotSpot = 0.0f;
switch (m_eetType) {
case ET_SIZING_RING_FLARE:
lsNew.ls_colColor = C_WHITE|CT_OPAQUE;
lsNew.ls_rHotSpot = 100.0f;
lsNew.ls_rFallOff = 300.0f;
lsNew.ls_plftLensFlare = &_lftWhiteGlowStarNG;
break;
case ET_SIZING_BIG_BLUE_FLARE:
lsNew.ls_colColor = C_WHITE|CT_OPAQUE;
lsNew.ls_rHotSpot = 500.0f*m_fSize;
lsNew.ls_rFallOff = 1000.0f*m_fSize;
lsNew.ls_plftLensFlare = &_lftBlueStarBlueReflections;
break;
default:
ASSERTALWAYS("Unknown light source");
}
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = NULL;
// setup light animation
lsNew.ls_paoLightAnimation = NULL;
if (m_aoLightAnimation.GetData()!=NULL) {
lsNew.ls_paoLightAnimation = &m_aoLightAnimation;
}
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
}
/************************************************************
* MAIN *
************************************************************/
procedures:
Main( ESpawnEffector eSpawn)
{
// set appearance
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE);
SetCollisionFlags(ECF_TOUCHMODEL);
SetFlags( GetFlags()|ENF_SEETHROUGH);
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// setup variables
m_eetType = eSpawn.eetType;
m_vDamageDir = eSpawn.vDamageDir;
m_tmStarted = _pTimer->CurrentTick();
m_tmLifeTime = eSpawn.tmLifeTime;
m_vFXDestination = eSpawn.vDestination;
m_fSize = eSpawn.fSize;
m_ctCount = eSpawn.ctCount;
m_bAlive = TRUE;
m_penModel = eSpawn.penModel;
m_penModel2 = eSpawn.penModel2;
m_bWaitTrigger = FALSE;
autowait(0.1f);
if(m_eetType==ET_MOVING_RING)
{
SetModel(MODEL_POWER_RING);
SetModelMainTexture(TEXTURE_POWER_RING);
en_fAcceleration = 1e6f;
FLOAT fSpeed = 550.0f;
SetDesiredTranslation(FLOAT3D(0,-fSpeed,0));
FLOAT fPathLen = GetPlacement().pl_PositionVector(2)-m_vFXDestination(2);
// t=s/v
m_tmLifeTime = fPathLen/fSpeed;
SwitchToModel();
FLOAT fSize = 36.0f;
FLOAT3D vStretch = FLOAT3D(fSize, fSize*2.0f, fSize);
GetModelObject()->StretchModel(vStretch);
ModelChangeNotify();
}
// spetial initializations
if(m_eetType==ET_SIZING_RING_FLARE)
{
m_bLightSource = TRUE;
m_iLightAnimation = 0;
}
if(m_eetType==ET_SIZING_BIG_BLUE_FLARE)
{
m_bLightSource = TRUE;
m_iLightAnimation = 1;
}
if(m_eetType==ET_MORPH_MODELS || m_eetType==ET_DISAPPEAR_MODEL || m_eetType==ET_APPEAR_MODEL)
{
m_bWaitTrigger = TRUE;
m_tmStarted = -1;
}
if(m_eetType==ET_DISAPPEAR_MODEL_NOW || m_eetType==ET_APPEAR_MODEL_NOW)
{
m_bWaitTrigger = FALSE;
m_tmStarted = _pTimer->CurrentTick();
}
// setup light source
if (m_bLightSource) { SetupLightSource(); }
while(_pTimer->CurrentTick()<m_tmStarted+m_tmLifeTime && m_bAlive || m_bWaitTrigger)
{
wait( 0.25f)
{
on( EBegin):{ resume;}
on( ETrigger):
{
if(m_eetType==ET_MORPH_MODELS || m_eetType==ET_DISAPPEAR_MODEL || m_eetType==ET_APPEAR_MODEL)
{
m_tmStarted = _pTimer->CurrentTick();
m_bWaitTrigger = FALSE;
// live forever
m_bAlive = TRUE;
}
resume;
}
on( ETimer):{ stop;}
}
// check if moving ring reached target position
if(m_eetType==ET_MOVING_RING)
{
if( GetPlacement().pl_PositionVector(2) < m_vFXDestination(2))
{
m_bAlive = FALSE;
}
}
}
Destroy();
return;
}
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,105 @@
339
%{
#include "Entities/StdH/StdH.h"
#include <Entities/MusicHolder.h>
%}
class CEnemyCounter : CRationalEntity {
name "EnemyCounter";
thumbnail "Thumbnails\\Counter.tbn";
features "HasName", "IsTargetable";
properties:
1 CEntityPointer m_penMainMusicHolder,
2 CTString m_strName "Name" 'N' ="",
4 INDEX m_iCountFrom "Count start" 'A' = 100,
5 INDEX m_iCount = -1,
components:
0 sound SOUND_TICK "Sounds\\Menu\\Select.wav",
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex"
functions:
class CMusicHolder *GetMusicHolder()
{
if (m_penMainMusicHolder==NULL) {
m_penMainMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0);
}
return (CMusicHolder *)&*m_penMainMusicHolder;
}
void StartCounting(void)
{
CMusicHolder *pmh = GetMusicHolder();
if (pmh==NULL) {
return;
}
pmh->m_penCounter = this;
m_iCount = m_iCountFrom;
}
void CountOne(void)
{
if (m_iCount>0) {
m_iCount-=1;
}
}
void StopCounting(void)
{
CMusicHolder *pmh = GetMusicHolder();
if (pmh==NULL) {
return;
}
m_iCount = 0;
pmh->m_penCounter = NULL;
}
procedures:
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
autowait(0.1f);
wait() {
on(EBegin): {
resume;
}
// when started
on (EStart): {
StartCounting();
resume;
}
// when stopped
on (EStop): {
StopCounting();
resume;
}
// when triggered
on (ETrigger): {
// if not started yet
if (m_iCount==-1) {
// start
StartCounting();
}
CountOne();
// if finished
if (m_iCount==0) {
// stop
StopCounting();
}
resume;
}
}
return;
}
};

View File

@ -0,0 +1,250 @@
313
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnemyBase";
uses "Entities/Debris";
uses "Entities/EnemyMarker";
enum EnemyDiveType {
0 EDT_GROUND_ONLY "Ground only", // can't dive
1 EDT_DIVE_ONLY "Dive only", // always dive can't walk
2 EDT_GROUND_DIVE "Ground and dive", // dive and walk
};
class export CEnemyDive : CEnemyBase {
name "Enemy Dive";
thumbnail "";
properties:
1 enum EnemyDiveType m_EedtType "Type" 'T' = EDT_DIVE_ONLY, // dive type
2 BOOL m_bInLiquid "In liquid" 'Q' = TRUE, // entity is in liquid
// moving/attack properties - CAN BE SET
// these following must be ordered exactly like this for GetProp() to function
10 FLOAT m_fDiveWalkSpeed = 1.0f, // dive walk speed
11 ANGLE m_aDiveWalkRotateSpeed = AngleDeg(10.0f), // dive walk rotate speed
12 FLOAT m_fDiveAttackRunSpeed = 1.0f, // dive attack run speed
13 ANGLE m_aDiveAttackRotateSpeed = AngleDeg(10.0f), // dive attack rotate speed
14 FLOAT m_fDiveCloseRunSpeed = 1.0f, // dive close run speed
15 ANGLE m_aDiveCloseRotateSpeed = AngleDeg(10.0f), // dive close rotate speed
20 FLOAT m_fDiveAttackDistance = 50.0f, // dive attack distance mode
21 FLOAT m_fDiveCloseDistance = 10.0f, // dive close distance mode
22 FLOAT m_fDiveAttackFireTime = 2.0f, // dive attack distance fire time
23 FLOAT m_fDiveCloseFireTime = 1.0f, // dive close distance fire time
24 FLOAT m_fDiveStopDistance = 0.0f, // dive stop moving toward enemy if closer than stop distance
25 FLOAT m_fDiveIgnoreRange = 200.0f, // dive cease attack if enemy farther
26 FLOAT m_fDiveLockOnEnemyTime = 0.0f, // dive time needed to fire
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
functions:
// overridable function for access to different properties of derived classes (flying/diving)
virtual FLOAT &GetProp(FLOAT &m_fBase)
{
if (m_bInLiquid) {
return *((&m_fBase)+(&m_fDiveWalkSpeed-&m_fWalkSpeed));
} else {
return m_fBase;
}
}
// diving enemies never use pathfinding
void StartPathFinding(void)
{
m_dtDestination=DT_PLAYERSPOTTED;
m_vPlayerSpotted = PlayerDestinationPos();
}
virtual void AdjustDifficulty(void)
{
FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed;
FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed;
// m_fDiveWalkSpeed *= fMoveSpeed;
// m_aDiveWalkRotateSpeed *= fMoveSpeed;
m_fDiveAttackRunSpeed *= fMoveSpeed;
m_aDiveAttackRotateSpeed *= fMoveSpeed;
m_fDiveCloseRunSpeed *= fMoveSpeed;
m_aDiveCloseRotateSpeed *= fMoveSpeed;
m_fDiveAttackFireTime *= 1/fAttackSpeed;
m_fDiveCloseFireTime *= 1/fAttackSpeed;
m_fDiveLockOnEnemyTime *= 1/fAttackSpeed;
CEnemyBase::AdjustDifficulty();
}
// close attack if possible
virtual BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) {
if (IsInPlaneFrustum(penTarget, fCosAngle)) {
return IsVisibleCheckAll(penTarget);
}
return FALSE;
};
/************************************************************
* POST MOVING *
************************************************************/
void PostMoving(void) {
CEnemyBase::PostMoving();
// change to liquid
if (m_EedtType!=EDT_GROUND_ONLY && !m_bInLiquid && en_fImmersionFactor>0.9f &&
(GetWorld()->wo_actContentTypes[en_iDnContent].ct_ulFlags&CTF_SWIMABLE)) {
m_bInLiquid = TRUE;
ChangeCollisionToLiquid();
SendEvent(ERestartAttack());
}
// change to ground
if (m_EedtType!=EDT_DIVE_ONLY && m_bInLiquid && (en_fImmersionFactor<0.5f || en_fImmersionFactor==1.0f) &&
en_penReference!=NULL && !(GetWorld()->wo_actContentTypes[en_iUpContent].ct_ulFlags&CTF_SWIMABLE)) {
m_bInLiquid = FALSE;
ChangeCollisionToGround();
SendEvent(ERestartAttack());
}
};
/************************************************************
* MOVING FUNCTIONS *
************************************************************/
// set desired rotation and translation to go/orient towards desired position
// and get the resulting movement type
virtual ULONG SetDesiredMovement(void)
{
// if not in air
if (!m_bInLiquid) {
// use base class
return CEnemyBase::SetDesiredMovement();
}
// get base rotation from base class
ULONG ulFlags = CEnemyBase::SetDesiredMovement();
// if we may move
if (m_fMoveSpeed>0.0f) {
// fix translation for 3d movement
FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation;
vTranslation(1) = 0.0f;
if (vTranslation(3)>0) {
vTranslation(3) = 0.0f;
}
vTranslation.Normalize();
vTranslation *= m_fMoveSpeed;
SetDesiredTranslation(vTranslation);
}
return ulFlags;
}
// check whether may move while attacking
BOOL MayMoveToAttack(void)
{
return WouldNotLeaveAttackRadius();
}
/************************************************************
* CLASS SUPPORT FUNCTIONS *
************************************************************/
// set entity position
void SetEntityPosition() {
switch (m_EedtType) {
case EDT_GROUND_ONLY: // can't dive
m_bInLiquid = FALSE;
break;
case EDT_DIVE_ONLY: // always dive can't walk
m_bInLiquid = TRUE;
break;
case EDT_GROUND_DIVE: // dive and walk
break;
}
// in liquid
if (m_bInLiquid) {
ChangeCollisionToLiquid();
} else {
ChangeCollisionToGround();
}
StandingAnim();
};
/************************************************************
* VIRTUAL FUNCTIONS THAT NEED OVERRIDE *
************************************************************/
virtual void ChangeCollisionToLiquid(void) {}
virtual void ChangeCollisionToGround(void) {}
procedures:
/************************************************************
* PROCEDURES WHEN NO ANY SPECIAL ACTION *
************************************************************/
/************************************************************
* ATTACK ENEMY PROCEDURES *
************************************************************/
// this is called to hit the player when near
Hit(EVoid) : CEnemyBase::Hit
{
if (m_bInLiquid) {
jump DiveHit();
} else {
jump GroundHit();
}
}
// this is called to shoot at player when far away or otherwise unreachable
Fire(EVoid) : CEnemyBase::Fire
{
if (m_bInLiquid) {
jump DiveFire();
} else {
jump GroundFire();
}
}
/************************************************************
* M A I N L O O P *
************************************************************/
// main loop
MainLoop(EVoid) : CEnemyBase::MainLoop {
SetEntityPosition();
jump CEnemyBase::MainLoop();
};
// dummy main
Main(EVoid) {
return;
};
/************************************************************
* VIRTUAL PROCEDURES THAT NEED OVERRIDE *
************************************************************/
// this is called to hit the player when near and you are on ground
GroundHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are on ground
GroundFire(EVoid)
{
return EReturn();
}
// this is called to hit the player when near and you are in water
DiveHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are in water
DiveFire(EVoid)
{
return EReturn();
}
};

View File

@ -0,0 +1,479 @@
311
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnemyBase";
uses "Entities/Debris";
uses "Entities/EnemyMarker";
enum EnemyFlyType {
0 EFT_GROUND_ONLY "Ground only", // can't fly
1 EFT_FLY_ONLY "Fly only", // always fly can't land
2 EFT_FLY_GROUND_GROUND "Fly(ground) - ground attack", // start attack on ground - ground
3 EFT_FLY_GROUND_AIR "Fly(ground) - air attack", // start attack in air - ground
4 EFT_FLY_AIR_GROUND "Fly(air) - ground attack", // start attack on ground - air
5 EFT_FLY_AIR_AIR "Fly(air) - air attack", // start attack in air - air
};
class export CEnemyFly : CEnemyBase {
name "Enemy Fly";
thumbnail "";
properties:
1 enum EnemyFlyType m_EeftType "Type" 'T' = EFT_FLY_GROUND_AIR, // fly type
2 BOOL m_bInAir = FALSE, // entity is in air
3 BOOL m_bAirAttack = FALSE, // start air attack
4 BOOL m_bStartInAir = FALSE, // initially in air
// moving/attack properties - CAN BE SET
16 FLOAT m_fGroundToAirSpeed = 2.0f, // ground to air speed
17 FLOAT m_fAirToGroundSpeed = 4.0f, // air to ground speed
18 FLOAT m_fAirToGroundMin = 1.0f, // how long to fly up before attacking
19 FLOAT m_fAirToGroundMax = 2.0f,
27 FLOAT m_fFlyHeight = 2.0f, // fly height above player handle
// these following must be ordered exactly like this for GetProp() to function
10 FLOAT m_fFlyWalkSpeed = 1.0f, // fly walk speed
11 ANGLE m_aFlyWalkRotateSpeed = AngleDeg(10.0f), // fly walk rotate speed
12 FLOAT m_fFlyAttackRunSpeed = 1.0f, // fly attack run speed
13 ANGLE m_aFlyAttackRotateSpeed = AngleDeg(10.0f), // fly attack rotate speed
14 FLOAT m_fFlyCloseRunSpeed = 1.0f, // fly close run speed
15 ANGLE m_aFlyCloseRotateSpeed = AngleDeg(10.0f), // fly close rotate speed
20 FLOAT m_fFlyAttackDistance = 50.0f, // fly attack distance mode
21 FLOAT m_fFlyCloseDistance = 10.0f, // fly close distance mode
22 FLOAT m_fFlyAttackFireTime = 2.0f, // fly attack distance fire time
23 FLOAT m_fFlyCloseFireTime = 1.0f, // fly close distance fire time
24 FLOAT m_fFlyStopDistance = 0.0f, // fly stop moving toward enemy if closer than stop distance
25 FLOAT m_fFlyIgnoreRange = 200.0f, // fly cease attack if enemy farther
26 FLOAT m_fFlyLockOnEnemyTime = 0.0f, // fly time needed to fire
// marker variables
100 BOOL m_bFlyToMarker = FALSE,
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
functions:
// overridable function for access to different properties of derived classes (flying/diving)
virtual FLOAT &GetProp(FLOAT &m_fBase)
{
if (m_bInAir) {
return *((&m_fBase)+(&m_fFlyWalkSpeed-&m_fWalkSpeed));
} else {
return m_fBase;
}
}
// get position you would like to go to when following player
virtual FLOAT3D PlayerDestinationPos(void)
{
// if not in air
if (!m_bInAir) {
// use base class
return CEnemyBase::PlayerDestinationPos();
}
// get distance to player
FLOAT fDist = CalcDist(m_penEnemy);
// determine height above from the distance
FLOAT fHeight;
// if in close attack range
if (fDist<=m_fFlyCloseDistance) {
// go to fixed height above player
fHeight = m_fFlyHeight;
// if in further
} else {
// fly more above if further
fHeight = m_fFlyHeight + fDist/5.0f;
}
// calculate the position from the height
return
m_penEnemy->GetPlacement().pl_PositionVector
+ FLOAT3D(m_penEnemy->en_mRotation(1, 2), m_penEnemy->en_mRotation(2, 2), m_penEnemy->en_mRotation(3, 2))
* fHeight;
}
// flying enemies never use pathfinding
void StartPathFinding(void)
{
if (m_bInAir) {
m_dtDestination=DT_PLAYERSPOTTED;
m_vPlayerSpotted = PlayerDestinationPos();
} else {
CEnemyBase::StartPathFinding();
}
}
virtual void AdjustDifficulty(void)
{
FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed;
FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed;
m_fFlyAttackFireTime *= 1/fAttackSpeed;
m_fFlyCloseFireTime *= 1/fAttackSpeed;
m_fFlyLockOnEnemyTime *= 1/fAttackSpeed;
// m_fFlyWalkSpeed *= fMoveSpeed;
// m_aFlyWalkRotateSpeed *= fMoveSpeed;
m_fFlyAttackRunSpeed *= fMoveSpeed;
m_aFlyAttackRotateSpeed *= fMoveSpeed;
m_fFlyCloseRunSpeed *= fMoveSpeed;
m_aFlyCloseRotateSpeed *= fMoveSpeed;
m_fGroundToAirSpeed *= fMoveSpeed;
m_fAirToGroundSpeed *= fMoveSpeed;
CEnemyBase::AdjustDifficulty();
}
// close attack if possible
virtual BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) {
if (IsInPlaneFrustum(penTarget, fCosAngle)) {
return IsVisibleCheckAll(penTarget);
}
return FALSE;
};
/************************************************************
* MOVING FUNCTIONS *
************************************************************/
// set desired rotation and translation to go/orient towards desired position
// and get the resulting movement type
virtual ULONG SetDesiredMovement(void)
{
// if not in air
if (!m_bInAir) {
// use base class
return CEnemyBase::SetDesiredMovement();
}
// get base rotation from base class
ULONG ulFlags = CEnemyBase::SetDesiredMovement();
// if we may move
if (m_fMoveSpeed>0.0f) {
// fix translation for 3d movement
FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation;
vTranslation(1) = 0.0f;
if (vTranslation(3)>0) {
vTranslation(3) = 0.0f;
}
vTranslation.Normalize();
vTranslation *= m_fMoveSpeed;
SetDesiredTranslation(vTranslation);
}
return ulFlags;
}
/************************************************************
* CLASS SUPPORT FUNCTIONS *
************************************************************/
// set entity position
void SetEntityPosition() {
switch (m_EeftType) {
case EFT_GROUND_ONLY: // ground only enemy
case EFT_FLY_GROUND_GROUND: // fly, on ground, start attack on ground
m_bAirAttack = FALSE;
m_bStartInAir = m_bInAir = FALSE;
m_bFlyToMarker = FALSE;
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING);
ChangeCollisionToGround();
break;
case EFT_FLY_GROUND_AIR: // fly, on ground, start attack in air
m_bAirAttack = TRUE;
m_bStartInAir = m_bInAir = FALSE;
m_bFlyToMarker = FALSE;
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING);
ChangeCollisionToGround();
break;
case EFT_FLY_AIR_GROUND: // fly, in air, start attack on ground
m_bAirAttack = FALSE;
m_bStartInAir = m_bInAir = TRUE;
m_bFlyToMarker = TRUE;
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING);
ChangeCollisionToAir();
break;
case EFT_FLY_ONLY: // air only enemy
case EFT_FLY_AIR_AIR: // fly, in air, start attack in air
m_bAirAttack = TRUE;
m_bStartInAir = m_bInAir = TRUE;
m_bFlyToMarker = TRUE;
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING);
ChangeCollisionToAir();
break;
}
StandingAnim();
};
/************************************************************
* VIRTUAL FUNCTIONS THAT NEED OVERRIDE *
************************************************************/
virtual FLOAT AirToGroundAnim(void) { return _pTimer->TickQuantum; }
virtual FLOAT GroundToAirAnim(void) { return _pTimer->TickQuantum; }
virtual void ChangeCollisionToAir(void) {}
virtual void ChangeCollisionToGround(void) {}
procedures:
/************************************************************
* PROCEDURES WHEN NO ANY SPECIAL ACTION *
************************************************************/
/*
#### !!!!
MoveToDestinationFlying(EVoid) {
m_fMoveFrequency = 0.25f;
m_fMoveTime = _pTimer->CurrentTick() + 45.0f;
while ((m_vDesiredPosition-GetPlacement().pl_PositionVector).Length()>m_fMoveSpeed*m_fMoveFrequency*2.0f &&
m_fMoveTime>_pTimer->CurrentTick()) {
wait (m_fMoveFrequency) {
on (EBegin) : { FlyToPosition(); }
on (ETimer) : { stop; }
}
}
return EReturn();
}
// Move to destination
MoveToDestination(EVoid) : CEnemyBase::MoveToDestination {
if (m_bFlyToMarker && !m_bInAir) {
autocall GroundToAir() EReturn;
} else if (!m_bFlyToMarker && m_bInAir) {
autocall AirToGround() EReturn;
}
// animation
if (m_bRunToMarker) {
RunningAnim();
} else {
WalkingAnim();
}
// fly to position
if (m_bInAir) {
jump MoveToDestinationFlying();
// move to position
} else {
jump CEnemyBase::MoveToDestination();
}
};*/
// return to start position
ReturnToStartPosition(EVoid) : CEnemyBase::ReturnToStartPosition
{
jump CEnemyBase::BeIdle();
/* // if on ground, but can fly
if (!m_bInAir && m_EeftType!=EFT_GROUND_ONLY) {
// fly up
autocall GroundToAir() EReturn;
}
GetWatcher()->StartPlayers(); // start watching
m_vDesiredPosition = m_vStartPosition-en_vGravityDir*2.0f;
m_vStartDirection = (GetPlacement().pl_PositionVector-m_vStartPosition).Normalize();
m_fMoveSpeed = m_fAttackRunSpeed;
m_aRotateSpeed = m_aAttackRotateSpeed;
RunningAnim();
autocall MoveToDestinationFlying() EReturn;
WalkingAnim();
m_vDesiredAngle = m_vStartDirection;
StopTranslating();
autocall CEnemyBase::RotateToStartDirection() EReturn;
// if should be on ground
if (m_bInAir && !m_bStartInAir) {
// fly down
autocall AirToGround() EReturn;
}
StopMoving();
StandingAnim();
jump CEnemyBase::BeIdle();*/
};
/************************************************************
* PROCEDURES WHEN HARMED *
************************************************************/
// Play wound animation and falling body part
BeWounded(EDamage eDamage) : CEnemyBase::BeWounded {
// land on ground
if (!(m_EeftType!=EFT_FLY_ONLY && m_bInAir && ((IRnd()&3)==0))) {
jump CEnemyBase::BeWounded(eDamage);
} else if (TRUE) {
m_bAirAttack = FALSE;
autocall AirToGround() EReturn;
}
return EReturn();
};
/************************************************************
* AIR - GROUND PROCEDURES *
************************************************************/
// air to ground
AirToGround(EVoid)
{
// land on brush
SetDesiredTranslation(FLOAT3D(0, -m_fAirToGroundSpeed, 0));
SetDesiredRotation(ANGLE3D(0, 0, 0));
WalkingAnim();
wait() {
on (EBegin) : { resume; }
// on brush stop
on (ETouch etouch) : {
if (etouch.penOther->GetRenderType() & RT_BRUSH) {
SetDesiredTranslation(FLOAT3D(0, 0, 0));
stop;
}
resume;
}
on (EDeath) : { pass; }
otherwise() : { resume; }
}
// on ground
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING);
m_bInAir = FALSE;
ChangeCollisionToGround();
// animation
wait(AirToGroundAnim()) {
on (EBegin) : { resume; }
on (ETimer) : { stop; }
on (EDeath) : { pass; }
otherwise() : { resume; }
}
return EReturn();
};
// ground to air
GroundToAir(EVoid)
{
// fly in air
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING);
m_bInAir = TRUE;
SetDesiredTranslation(FLOAT3D(0, m_fGroundToAirSpeed, 0));
SetDesiredRotation(ANGLE3D(0, 0, 0));
ChangeCollisionToAir();
// animation
wait(GroundToAirAnim()) {
on (EBegin) : { resume; }
on (EDeath) : { pass; }
on (ETimer) : { stop; }
otherwise() : { resume; }
}
// move in air further
WalkingAnim();
wait(Lerp(m_fAirToGroundMin, m_fAirToGroundMax, FRnd())) {
on (EBegin) : { resume; }
on (EDeath) : { pass; }
on (ETimer) : { stop; }
otherwise() : { resume; }
}
SetDesiredTranslation(FLOAT3D(0, 0, 0));
return EReturn();
};
/************************************************************
* ATTACK ENEMY PROCEDURES *
************************************************************/
// initialize attack is overridden to switch fly/walk modes if needed
AttackEnemy() : CEnemyBase::AttackEnemy
{
// air attack
if (m_bAirAttack) {
// ground to air
if (!m_bInAir) {
autocall GroundToAir() EReturn;
}
// ground attack
} else if (TRUE) {
// air to ground
if (m_bInAir) {
autocall AirToGround() EReturn;
}
}
jump CEnemyBase::AttackEnemy();
}
// this is called to hit the player when near
Hit(EVoid) : CEnemyBase::Hit
{
if (m_bInAir) {
jump FlyHit();
} else {
jump GroundHit();
}
}
// this is called to shoot at player when far away or otherwise unreachable
Fire(EVoid) : CEnemyBase::Fire
{
if (m_bInAir) {
jump FlyFire();
} else {
jump GroundFire();
}
}
/************************************************************
* D E A T H *
************************************************************/
Death(EVoid) : CEnemyBase::Death {
// clear fly flag
SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING);
ChangeCollisionToGround();
jump CEnemyBase::Death();
};
/************************************************************
* M A I N L O O P *
************************************************************/
// main loop
MainLoop(EVoid) : CEnemyBase::MainLoop {
SetEntityPosition();
jump CEnemyBase::MainLoop();
};
// dummy main
Main(EVoid) {
return;
};
/************************************************************
* VIRTUAL PROCEDURES THAT NEED OVERRIDE *
************************************************************/
// this is called to hit the player when near and you are on ground
GroundHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are on ground
GroundFire(EVoid)
{
return EReturn();
}
// this is called to hit the player when near and you are in air
FlyHit(EVoid)
{
return EReturn();
}
// this is called to shoot at player when far away or otherwise unreachable and you are in air
FlyFire(EVoid)
{
return EReturn();
}
};

View File

@ -0,0 +1,53 @@
302
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
class CEnemyMarker: CMarker {
name "Enemy Marker";
thumbnail "Thumbnails\\EnemyMarker.tbn";
properties:
1 FLOAT m_fWaitTime = 0.0f, // time to wait(or do anything) until go to another marker
3 RANGE m_fMarkerRange "Marker Range" 'M' = 0.0f, // range around marker (marker doesn't have to be hit directly)
11 RANGE m_fPatrolAreaInner "Patrol Area Inner" 'R' = 0.0f, // patrol area inner circle
12 RANGE m_fPatrolAreaOuter "Patrol Area Outer" 'E' = 0.0f, // patrol area outer circle
13 FLOAT m_fPatrolTime "Patrol Time" 'P' = 0.0f, // time to patrol around
14 enum BoolEType m_betRunToMarker "Run to marker" 'O' = BET_IGNORE, // run to marker
15 enum BoolEType m_betFly "Fly" 'F' = BET_IGNORE, // fly if you can
16 enum BoolEType m_betBlind "Blind" 'B' = BET_IGNORE,
17 enum BoolEType m_betDeaf "Deaf" 'D' = BET_IGNORE,
components:
1 model MODEL_MARKER "Models\\Editor\\EnemyMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\EnemyMarker.tex"
functions:
/* Check if entity is moved on a route set up by its targets. */
BOOL MovesByTargetedRoute(CTString &strTargetProperty) const {
strTargetProperty = "Target";
return TRUE;
};
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const {
fnmMarkerClass = CTFILENAME("Classes\\EnemyMarker.ecl");
strTargetProperty = "Target";
return TRUE;
}
procedures:
Main() {
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
return;
}
};

View File

@ -0,0 +1,283 @@
312
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnemyBase";
class export CEnemyRunInto : CEnemyBase {
name "Enemy Run Into";
thumbnail "";
properties:
1 CEntityPointer m_penLastTouched, // last touched live entity
2 FLOAT m_fLastTouchedTime=0.0f, // last touched live entity time
3 BOOL m_bWhileLoop=FALSE, // internal for loops
5 FLOAT m_fMassKicked = 0.0f, // total mass kicked in one attack
// moving properties - CAN BE SET
10 ANGLE m_fAttackRotateRunInto = 1.0f, // attack rotate speed before run into enemy
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
functions:
virtual void AdjustDifficulty(void)
{
FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed;
m_fAttackRotateRunInto *= fMoveSpeed;
CEnemyBase::AdjustDifficulty();
}
/************************************************************
* ATTACK SPECIFIC *
************************************************************/
void IncreaseKickedMass(CEntity *pen) {
EntityInfo *peiTarget = (EntityInfo*) (pen->GetEntityInfo());
if (peiTarget!=NULL) {
m_fMassKicked += peiTarget->fMass;
}
};
/************************************************************
* VIRTUAL ATTACK FUNCTIONS THAT NEED OVERRIDE *
************************************************************/
// touched another live entity
virtual void LiveEntityTouched(ETouch etouch) {};
// touched entity with higher mass
virtual BOOL HigherMass(void) { return FALSE; }
procedures:
/************************************************************
* ATTACK ENEMY PROCEDURES *
************************************************************/
// attack range -> fire and move toward enemy
Fire() : CEnemyBase::Fire {
m_fMassKicked = 0.0f;
m_penLastTouched = NULL;
jump RotateToEnemy();
};
RotateToEnemy() {
// if the enemy not alive or deleted
if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) {
SetTargetNone();
return EReturn();
}
// rotate to enemy
m_bWhileLoop = TRUE;
while (m_penEnemy!=NULL && m_bWhileLoop) {
m_fMoveFrequency = 0.1f;
wait(m_fMoveFrequency) {
// attack target
on (EBegin) : {
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
// rotate to enemy
if (!IsInPlaneFrustum(m_penEnemy, CosFast(15.0f))) {
m_aRotateSpeed = m_fAttackRotateRunInto;
m_fMoveSpeed = 0.0f;
// adjust direction and speed
ULONG ulFlags = SetDesiredMovement();
MovementAnimation(ulFlags);
} else {
m_aRotateSpeed = 0.0f;
m_fMoveSpeed = 0.0f;
m_bWhileLoop = FALSE;
}
resume;
}
on (ESound) : { resume; } // ignore all sounds
on (EWatch) : { resume; } // ignore watch
on (ETimer) : { stop; } // timer tick expire
}
}
jump RunIntoEnemy();
};
/* WalkToEnemy() {
// if the enemy not alive or deleted
if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) {
SetTargetNone();
return EReturn();
}
// walk to enemy if can't be seen
while (!CanAttackEnemy(m_penEnemy, CosFast(30.0f))) {
m_fMoveFrequency = 0.1f;
wait(m_fMoveFrequency) {
// move to target
on (EBegin) : {
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
m_fMoveSpeed = m_fWalkSpeed;
m_aRotateSpeed = m_aWalkRotateSpeed;
// adjust direction and speed
ULONG ulFlags = SetDesiredMovement();
MovementAnimation(ulFlags);
}
on (ESound) : { resume; } // ignore all sounds
on (EWatch) : { resume; } // ignore watch
on (ETimer) : { stop; } // timer tick expire
}
}
jump StartRunIntoEnemy();
};
StartRunIntoEnemy() {
// if the enemy not alive or deleted
if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) {
SetTargetNone();
return EReturn();
}
// run to enemy
m_bWhileLoop = TRUE;
m_fMoveFrequency = 0.5f;
wait(m_fMoveFrequency) {
on (EBegin) : {
// if enemy can't be seen stop running
if (!SeeEntity(m_penEnemy, CosFast(90.0f))) {
m_bWhileLoop = FALSE;
stop;
}
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
// move to enemy
m_fMoveSpeed = m_fAttackRunSpeed;
m_aRotateSpeed = m_aAttackRotateSpeed;
// adjust direction and speed
SetDesiredMovement();
RunningAnim();
resume;
}
on (ETouch) : { resume; }
on (ETimer) : { stop; } // timer tick expire
}
jump RunIntoEnemy();
};
*/
RunIntoEnemy() {
// if the enemy not alive or deleted
if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) {
SetTargetNone();
return EReturn();
}
// run to enemy
m_bWhileLoop = TRUE;
while(m_penEnemy!=NULL && m_bWhileLoop) {
m_fMoveFrequency = 0.1f;
wait(m_fMoveFrequency) {
on (EBegin) : {
// if enemy can't be seen, or too close
if (!SeeEntity(m_penEnemy, CosFast(90.0f)) || CalcDist(m_penEnemy)<6.75f) {
// continue past it
m_bWhileLoop = FALSE;
stop;
}
// move to enemy
m_fMoveSpeed = m_fAttackRunSpeed;
m_aRotateSpeed = m_fAttackRotateRunInto;
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
SetDesiredMovement();
RunningAnim();
// make fuss
AddToFuss();
resume;
}
// if touch another
on (ETouch etouch) : {
// if the entity is live
if (etouch.penOther->GetFlags()&ENF_ALIVE) {
// react to hitting it
LiveEntityTouched(etouch);
// if hit something bigger than us
if (HigherMass()) {
// stop attack
m_penLastTouched = NULL;
return EReturn();
}
// if hit the enemy
if (etouch.penOther==m_penEnemy) {
// continue past it
m_bWhileLoop = FALSE;
stop;
}
// if hit wall
} else if (!(etouch.penOther->GetPhysicsFlags()&EPF_MOVABLE) &&
(FLOAT3D(etouch.plCollision)% -en_vGravityDir)<CosFast(50.0f)) {
// stop run to enemy
m_penLastTouched = NULL;
return EReturn();
}
resume;
}
on (ETimer) : { stop; } // timer tick expire
on (EDeath) : { pass; }
otherwise() : { resume; }
}
}
jump RunAwayFromEnemy();
};
RunAwayFromEnemy() {
// if the enemy not alive or deleted
if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) {
SetTargetNone();
return EReturn();
}
// run in direction for 1.3 seconds
StopRotating();
wait(1.3f) {
on (EBegin) : { resume; }
on (ETouch etouch) : {
// live entity touched
if (etouch.penOther->GetFlags()&ENF_ALIVE) {
LiveEntityTouched(etouch);
// stop moving on higher mass
if (HigherMass()) {
m_penLastTouched = NULL;
return EReturn();
}
// stop go away from enemy
} else if (!(etouch.penOther->GetPhysicsFlags()&EPF_MOVABLE) &&
(FLOAT3D(etouch.plCollision)% -en_vGravityDir)<CosFast(50.0f)) {
m_penLastTouched = NULL;
return EReturn();
}
resume;
}
on (ETimer) : { stop; }
on (EDeath) : { pass; }
otherwise() : { resume; }
}
m_penLastTouched = NULL;
return EReturn();
};
// main loop
MainLoop(EVoid) : CEnemyBase::MainLoop {
jump CEnemyBase::MainLoop();
};
// dummy main
Main(EVoid) {
return;
};
};

View File

@ -0,0 +1,389 @@
304
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
enum EnemySpawnerType {
0 EST_SIMPLE "Simple", // spawns on trigger
1 EST_RESPAWNER "Respawner", // respawn after death
2 EST_DESTROYABLE "Destroyable", // spawns untill killed
3 EST_TRIGGERED "Triggered", // spawn one group on each trigger
4 EST_TELEPORTER "Teleporter", // teleport the target instead copying it - usable only once
5 EST_RESPAWNERBYONE "RespawnerbyOne", // respawn only one (not entire group) after death
};
class CEnemySpawner: CRationalEntity {
name "Enemy Spawner";
thumbnail "Thumbnails\\EnemySpawner.tbn";
features "HasName", "HasTarget", "IsTargetable";
properties:
1 CEntityPointer m_penTarget "Template Target" 'T' COLOR(C_BLUE|0x20), // template entity to duplicate
2 CTString m_strDescription = "",
3 CTString m_strName "Name" 'N' = "Enemy spawner",
6 RANGE m_fInnerCircle "Circle inner" 'V' = 0.0f, // inner circle for creation
7 RANGE m_fOuterCircle "Circle outer" 'B' = 0.0f, // outer circle for creation
9 FLOAT m_tmDelay "Wait delay" 'W' = 0.0f, // how long to delay before spawning
16 FLOAT m_tmSingleWait "Single delay" 'O' = 0.1f, // delay inside one group
5 FLOAT m_tmGroupWait "Group delay" 'G' = 0.1f, // delay between two groups
17 INDEX m_ctGroupSize "Group size" = 1,
8 INDEX m_ctTotal "Total count" 'C' = 1, // max. number of spawned enemies
13 CEntityPointer m_penPatrol "Patrol target" 'P' COLOR(C_lGREEN|0xFF), // for spawning patrolling
15 enum EnemySpawnerType m_estType "Type" 'Y' = EST_SIMPLE, // type of spawner
18 BOOL m_bTelefrag "Telefrag" 'F' = FALSE, // telefrag when spawning
19 BOOL m_bSpawnEffect "SpawnEffect" 'S' = TRUE, // show effect and play sound
20 BOOL m_bDoubleInSerious "Double in serious mode" = FALSE,
21 CEntityPointer m_penSeriousTarget "Template for Serious" COLOR(C_RED|0x20),
50 CSoundObject m_soSpawn, // sound channel
51 INDEX m_iInGroup=0, // in group counter for loops
components:
1 model MODEL_ENEMYSPAWNER "Models\\Editor\\EnemySpawner.mdl",
2 texture TEXTURE_ENEMYSPAWNER "Models\\Editor\\EnemySpawner.tex",
3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
functions:
void Precache(void) {
PrecacheClass(CLASS_BASIC_EFFECT, BET_TELEPORT);
}
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",(const char*) m_penTarget->GetName());
if (m_penSeriousTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s, %s",
(const char*) m_penTarget->GetName(),(const char*) m_penSeriousTarget->GetName());
}
}
((CTString&)m_strDescription) = EnemySpawnerType_enum.NameForValue(INDEX(m_estType))
+ m_strDescription;
return m_strDescription;
}
// check if one template is valid for this spawner
BOOL CheckTemplateValid(CEntity *pen)
{
if (pen==NULL || !IsDerivedFromClass(pen, "Enemy Base")) {
return FALSE;
}
if (m_estType==EST_TELEPORTER) {
return !(((CEnemyBase&)*pen).m_bTemplate);
} else {
return ((CEnemyBase&)*pen).m_bTemplate;
}
}
BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget)
{
if( slPropertyOffset == offsetof(CEnemySpawner, m_penTarget))
{
return CheckTemplateValid(penTarget);
}
else if( slPropertyOffset == offsetof(CEnemySpawner, m_penPatrol))
{
return (penTarget!=NULL && IsDerivedFromClass(penTarget, "Enemy Marker"));
}
else if( slPropertyOffset == offsetof(CEnemySpawner, m_penSeriousTarget))
{
return CheckTemplateValid(penTarget);
}
return CEntity::IsTargetValid(slPropertyOffset, penTarget);
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
if (m_penTarget==NULL) { return FALSE; }
m_penTarget->FillEntityStatistics(pes);
pes->es_ctCount = m_ctTotal;
pes->es_strName += " (spawned)";
if (m_penSeriousTarget!=NULL) {
pes->es_strName += " (has serious)";
}
return TRUE;
}
// spawn new entity
void SpawnEntity(BOOL bCopy) {
// spawn new entity if of class basic enemy
if (CheckTemplateValid(m_penTarget)) {
CEntity *pen = NULL;
if (bCopy) {
// copy template entity
pen = GetWorld()->CopyEntityInWorld( *m_penTarget,
CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) );
// change needed properties
pen->End();
CEnemyBase *peb = ((CEnemyBase*)pen);
peb->m_bTemplate = FALSE;
if (m_estType==EST_RESPAWNER || m_estType==EST_RESPAWNERBYONE) {
peb->m_penSpawnerTarget = this;
}
if (m_penPatrol!=NULL) {
peb->m_penMarker = m_penPatrol;
}
pen->Initialize();
} else {
pen = m_penTarget;
m_penTarget = NULL;
}
// adjust circle radii to account for enemy size
FLOAT fEntityR = 0;
if (pen->en_pciCollisionInfo!=NULL) {
fEntityR = pen->en_pciCollisionInfo->GetMaxFloorRadius();
}
FLOAT fOuterCircle = ClampDn(m_fOuterCircle-fEntityR, 0.0f);
FLOAT fInnerCircle = ClampUp(m_fInnerCircle+fEntityR, fOuterCircle);
// calculate new position
FLOAT fR = fInnerCircle + FRnd()*(fOuterCircle-fInnerCircle);
FLOAT fA = FRnd()*360.0f;
CPlacement3D pl(FLOAT3D(CosFast(fA)*fR, 0.05f, SinFast(fA)*fR), ANGLE3D(0, 0, 0));
pl.RelativeToAbsolute(GetPlacement());
// teleport back
pen->Teleport(pl, m_bTelefrag);
// spawn teleport effect
if (m_bSpawnEffect) {
ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_TELEPORT;
ese.vNormal = FLOAT3D(0,1,0);
FLOATaabbox3D box;
pen->GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm()*2;
ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize);
CEntityPointer penEffect = CreateEntity(pl, CLASS_BASIC_EFFECT);
penEffect->Initialize(ese);
}
}
};
procedures:
// spawn one group of entities
SpawnGroup()
{
// no enemies in group yet
m_iInGroup = 0;
// repeat forever
while(TRUE) {
// spawn one enemy
SpawnEntity(TRUE);
// count total enemies spawned
m_ctTotal--;
// if no more left
if (m_ctTotal<=0) {
// finish entire spawner
return EEnd();
}
// count enemies in group
m_iInGroup++;
// if entire group spawned
if (m_iInGroup>=m_ctGroupSize) {
// finish
return EReturn();
}
// wait between two entities in group
wait(m_tmSingleWait) {
on (EBegin) : { resume; }
on (ETimer) : { stop; }
otherwise() : { pass; }
}
}
}
// simple spawner
Simple()
{
// wait to be triggered
wait() {
on (EBegin) : { resume; }
on (ETrigger) : { stop; };
on (EStart) : { stop; };
otherwise() : { pass; }
}
// if should delay
if (m_tmDelay>0) {
// wait delay
autowait(m_tmDelay);
}
// repeat
while(TRUE) {
// spawn one group
autocall SpawnGroup() EReturn;
// delay between groups
autowait(m_tmGroupWait);
}
}
// teleports the template
Teleporter()
{
// wait to be triggered
wait() {
on (EBegin) : { resume; }
on (ETrigger) : { stop; };
on (EStart) : { stop; };
otherwise() : { pass; }
}
// if should delay
if (m_tmDelay>0) {
// wait delay
autowait(m_tmDelay);
}
// teleport it
SpawnEntity(FALSE);
// end the spawner
return EEnd();
}
// respawn enemies when killed
Respawner()
{
// repeat
while(TRUE) {
// wait to be triggered
wait() {
on (EBegin) : { resume; }
on (ETrigger) : { stop; };
on (EStart) : { stop; };
otherwise() : { pass; }
}
// if should delay
if (m_tmDelay>0) {
// wait delay
autowait(m_tmDelay);
}
// spawn one group
autocall SpawnGroup() EReturn;
// if should continue respawning by one
if (m_estType==EST_RESPAWNERBYONE) {
// set group size to 1
m_ctGroupSize = 1;
}
// wait a bit to recover
autowait(0.1f);
}
}
DestroyableInactive()
{
waitevent() EActivate;
jump DestroyableActive();
}
DestroyableActiveSpawning()
{
// repeat
while(TRUE) {
// spawn one group
autocall SpawnGroup() EReturn;
// delay between groups
autowait(m_tmGroupWait);
}
}
DestroyableActive()
{
autocall DestroyableActiveSpawning() EDeactivate;
jump DestroyableInactive();
}
// spawn new entities until you are stopped
Destroyable()
{
// start in inactive state and do until stopped
autocall DestroyableInactive() EStop;
// finish
return EEnd();
}
Main() {
// init as nothing
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_ENEMYSPAWNER);
SetModelMainTexture(TEXTURE_ENEMYSPAWNER);
// set range
if (m_fInnerCircle > m_fOuterCircle) {
m_fInnerCircle = m_fOuterCircle;
}
// check target
if (m_penTarget!=NULL) {
if (!IsDerivedFromClass(m_penTarget, "Enemy Base")) {
WarningMessage("Target '%s' is of wrong class!", (const char*)m_penTarget->GetName());
m_penTarget = NULL;
}
}
if (m_penSeriousTarget!=NULL) {
if (!IsDerivedFromClass(m_penSeriousTarget, "Enemy Base")) {
WarningMessage("Target '%s' is of wrong class!", (const char*)m_penSeriousTarget->GetName());
m_penSeriousTarget = NULL;
}
}
// never start ai in wed
autowait(_pTimer->TickQuantum);
if (m_bDoubleInSerious && GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) {
m_ctGroupSize*=2;
m_ctTotal*=2;
}
if (m_penSeriousTarget!=NULL && GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) {
m_penTarget = m_penSeriousTarget;
}
wait() {
on(EBegin) : {
if(m_estType==EST_SIMPLE) {
call Simple();
} else if(m_estType==EST_TELEPORTER) {
call Teleporter();
} else if(m_estType==EST_RESPAWNER || m_estType==EST_RESPAWNERBYONE || m_estType==EST_TRIGGERED) {
call Respawner();
} else if(m_estType==EST_DESTROYABLE) {
call Destroyable();
}
}
on(EDeactivate) : {
stop;
}
on(EStop) : {
stop;
}
on(EEnd) : {
stop;
}
}
Destroy();
return;
};
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,416 @@
900
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/EnvironmentMarker";
uses "Entities/WatchPlayers";
class CEnvironmentBase: CMovableEntity {
name "Environment Base";
thumbnail "Thumbnails\\EnvironmentBase.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Base Environment",
2 CTString m_strDescription = "",
3 RANGE m_fDistance "Range" 'R' = 100.0f, // distance when player is seen
4 FLOAT m_fStretch "Stretch" 'S' = 1.0f,
5 CEntityPointer m_penTarget "Target" 'T',
6 CEntityPointer m_penWatcher,
7 FLOAT m_fWatcherFrequency "Watcher frequency" = 2.0f, // watcher will look every x seconds for players
8 FLOAT3D m_vDesiredPosition = FLOAT3D(0, 0, 0), // desired position for moving
10 FLOAT m_fMoveSpeed "Move speed" 'V' = 2.0f,
11 FLOAT m_fRotateSpeed "Rotate speed" 'B' = 60.0f,
12 FLOAT m_fMoveFrequency "Move frequency" = 0.5f,
13 BOOL m_bUseWatcher "Use watcher" = FALSE, // use individual watcher
14 BOOL m_bFlying "Flying" 'F' = FALSE, // flying model
16 FLOAT m_fWaitTime = 0.0f,
20 CTFileName m_fnMdl "Model" 'M' = CTFILENAME("Models\\Editor\\Axis.mdl"),
21 CTFileName m_fnTex "Texture" 'X' = CTString(""),
22 ANIMATION m_iAnim "Animation" =0,
25 CTFileName m_fnAtt1Mdl "Attachment 1 Model" = CTString(""),
26 CTFileName m_fnAtt1Tex "Attachment 1 Texture" = CTString(""),
27 INDEX m_iAtt1Position "Attachment 1 position"=0,
28 ANIMATION m_iAtt1Anim "Attachment 1 animation"=0,
30 CTFileName m_fnAtt2Mdl "Attachment 2 Model" = CTString(""),
31 CTFileName m_fnAtt2Tex "Attachment 2 Texture" = CTString(""),
32 INDEX m_iAtt2Position "Attachment 2 position"=1,
33 ANIMATION m_iAtt2Anim "Attachment 2 animation"=0,
35 CTFileName m_fnAtt3Mdl "Attachment 3 Model" = CTString(""),
36 CTFileName m_fnAtt3Tex "Attachment 3 Texture" = CTString(""),
37 INDEX m_iAtt3Position "Attachment 3 position"=1,
38 ANIMATION m_iAtt3Anim "Attachment 3 animation"=0,
components:
1 class CLASS_WATCHPLAYERS "Classes\\WatchPlayers.ecl",
functions:
/* Check if entity is moved on a route set up by its targets. */
BOOL MovesByTargetedRoute(CTString &strTargetProperty) const {
strTargetProperty = "Target";
return TRUE;
};
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const {
fnmMarkerClass = CTFILENAME("Classes\\EnvironmentMarker.ecl");
strTargetProperty = "Target";
return TRUE;
};
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s",(const char*) m_penTarget->GetName());
}
return m_strDescription;
};
/* Get anim data for given animation property - return NULL for none. */
CAnimData *GetAnimData(SLONG slPropertyOffset) {
if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAnim)) {
return GetModelObject()->GetData();
} else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt1Anim)) {
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt1Position);
if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); }
return CEntity::GetAnimData(slPropertyOffset);
} else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt2Anim)) {
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt2Position);
if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); }
return CEntity::GetAnimData(slPropertyOffset);
} else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt3Anim)) {
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt3Position);
if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); }
return CEntity::GetAnimData(slPropertyOffset);
} else {
return CEntity::GetAnimData(slPropertyOffset);
}
};
/************************************************************
* MOVE FUNCTIONS *
************************************************************/
// switch to next marker
BOOL NextMarker(void) {
if (m_penTarget==NULL) {
return FALSE;
}
// assure valid target
if (m_penTarget!=NULL && !IsOfClass(m_penTarget, "Environment Marker")) {
WarningMessage("Target '%s' is not of Environment Marker class!",(const char*) m_penTarget->GetName());
m_penTarget = NULL;
return FALSE;
}
// get next marker
CMarker *penTarget = (CMarker *)(CEntity*)m_penTarget;
CMarker *penNextTarget = (CMarker *)(CEntity*)penTarget->m_penTarget;
// if got to end
if (penNextTarget==NULL) {
return FALSE;
}
// remember next marker as current target
m_penTarget = penNextTarget;
return TRUE;
};
// calculate rotation
void CalcRotation(ANGLE aWantedHeadingRelative, ANGLE3D &aRotation) {
// normalize it to [-180,+180] degrees
aWantedHeadingRelative = NormalizeAngle(aWantedHeadingRelative);
// if desired position is left
if (aWantedHeadingRelative<-m_fRotateSpeed*m_fMoveFrequency) {
// start turning left
aRotation(1) = -m_fRotateSpeed;
// if desired position is right
} else if (aWantedHeadingRelative>m_fRotateSpeed*m_fMoveFrequency) {
// start turning right
aRotation(1) = +m_fRotateSpeed;
// if desired position is more-less ahead
} else {
aRotation(1) = aWantedHeadingRelative/m_fMoveFrequency;
}
};
// stop moving
void StopMoving(void) {
SetDesiredRotation(ANGLE3D(0, 0, 0));
SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f));
};
// move to position
void MoveToPosition(void) {
FLOAT3D vDesiredAngle;
// desired angle vector
vDesiredAngle = (m_vDesiredPosition - GetPlacement().pl_PositionVector).Normalize();
// find relative heading towards the desired angle
ANGLE3D aRotation(0,0,0);
CalcRotation(GetRelativeHeading(vDesiredAngle), aRotation);
// determine translation speed
FLOAT3D vTranslation(0.0f, 0.0f, 0.0f);
vTranslation(3) = -m_fMoveSpeed;
// if flying set y axis translation speed
if (m_bFlying) {
vTranslation(2) = Sgn(vDesiredAngle(2)) * m_fMoveSpeed/10;
}
// start moving
SetDesiredRotation(aRotation);
SetDesiredTranslation(vTranslation);
};
// calc destination
void CalcDestination() {
// new position to walk to
FLOAT fR = FRnd()*((CEnvironmentMarker&)*m_penTarget).m_fMarkerRange;
FLOAT fA = FRnd()*360.0f;
m_vDesiredPosition = m_penTarget->GetPlacement().pl_PositionVector +
FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR);
};
// marker parameters
void MarkerParameters() {
if (m_penTarget != NULL) {
CEnvironmentMarker &em = (CEnvironmentMarker&)*m_penTarget;
if (em.m_fMoveSpeed > 0.0f) {
m_fMoveSpeed = em.m_fMoveSpeed;
}
if (em.m_fRotateSpeed > 0.0f) {
m_fRotateSpeed = em.m_fRotateSpeed;
}
}
};
/************************************************************
* INITIALIZE FUNCTIONS *
************************************************************/
void Initialize(void) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING&~(EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY));
SetCollisionFlags(ECF_MODEL);
// set model stretch -- MUST BE DONE BEFORE SETTING MODEL!
GetModelObject()->mo_Stretch = FLOAT3D( m_fStretch, m_fStretch, m_fStretch);
// set appearance
SetModel(m_fnMdl);
GetModelObject()->PlayAnim(m_iAnim, AOF_LOOPING);
if( m_fnTex != CTString("")) {
GetModelObject()->mo_toTexture.SetData_t(m_fnTex);
}
GetModelObject()->RemoveAllAttachmentModels();
AddAttachment( m_iAtt1Position, m_fnAtt1Mdl, m_fnAtt1Tex);
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt1Position);
if( pamo != NULL) {
pamo->amo_moModelObject.StartAnim( m_iAtt1Anim);
}
if( (m_iAtt2Position != m_iAtt1Position) && (m_fnAtt1Mdl != m_fnAtt2Mdl) ) {
AddAttachment( m_iAtt2Position, m_fnAtt2Mdl, m_fnAtt2Tex);
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt2Position);
if( pamo != NULL) {
pamo->amo_moModelObject.StartAnim( m_iAtt2Anim);
}
}
if( (m_iAtt3Position != m_iAtt1Position) && (m_fnAtt1Mdl != m_fnAtt3Mdl) &&
(m_iAtt3Position != m_iAtt2Position) && (m_fnAtt2Mdl != m_fnAtt3Mdl) ) {
AddAttachment( m_iAtt3Position, m_fnAtt3Mdl, m_fnAtt3Tex);
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt3Position);
if( pamo != NULL) {
pamo->amo_moModelObject.StartAnim( m_iAtt3Anim);
}
}
// assure valid target
if (m_penTarget!=NULL && !IsOfClass(m_penTarget, "Environment Marker")) {
WarningMessage("Target '%s' is not of Environment Marker class!", (const char*)m_penTarget->GetName());
m_penTarget = NULL;
}
};
/************************************************************
* WATCHER FUNCTIONS *
************************************************************/
void InitializeWatcher(FLOAT fWaitTime) {
// spawn player watcher
m_penWatcher = CreateEntity(GetPlacement(), CLASS_WATCHPLAYERS);
m_penWatcher->Initialize(EVoid());
// setup player watcher
CWatchPlayers &pw = (CWatchPlayers&)*m_penWatcher;
pw.m_penOwner = this;
pw.m_fWaitTime = 2.0f;
pw.m_fDistance = m_fDistance;
pw.m_bRangeWatcher = FALSE;
pw.m_eetEventClose = EET_ENVIRONMENTSTART;
pw.m_eetEventFar = EET_ENVIRONMENTSTOP;
};
/************************************************************
* ANIMATION FUCNTIONS *
************************************************************/
// play default anim
void PlayDefaultAnim(void) {
GetModelObject()->PlayAnim(m_iAnim, AOF_LOOPING|AOF_NORESTART);
};
// play marker animation
void PlayMarkerAnimation(void) {
if (m_penTarget != NULL) {
GetModelObject()->PlayAnim(((CEnvironmentMarker&)*m_penTarget).m_iAnim, AOF_LOOPING|AOF_NORESTART);
}
};
// change default anim
void ChangeDefaultAnim(void) {
if (m_penTarget != NULL && ((CEnvironmentMarker&)*m_penTarget).m_bChangeDefaultAnim) {
m_iAnim = ((CEnvironmentMarker&)*m_penTarget).m_iAnim;
}
};
// wait on marker
void WaitOnMarker(void) {
if (m_penTarget != NULL) {
CEnvironmentMarker &em = (CEnvironmentMarker&)*m_penTarget;
m_fWaitTime = em.m_fWaitTime; // wait time
m_fWaitTime += FRnd() * em.m_fRandomTime; // random wait time
// fixed anim length
if (em.m_bFixedAnimLength) {
m_fWaitTime = floor(m_fWaitTime + 0.5f);
}
}
};
procedures:
/************************************************************
* SUPPORT PROCEDURES *
************************************************************/
// move to marker
MoveToMarker(EVoid) {
// if next marker exist
if (NextMarker()) {
// destination
CalcDestination();
// move to marker
while ((m_vDesiredPosition-GetPlacement().pl_PositionVector).Length() > 5.0f) {
wait(m_fMoveFrequency) {
on (EBegin) : {
MoveToPosition();
resume;
}
on (ETimer) : { stop; }
}
}
}
// stop moving
StopMoving();
return EEnd();
};
/************************************************************
* A C T I O N S *
************************************************************/
// activate
Activate(EVoid) {
wait() {
on (EBegin) : { call DoAction(); }
on (EEnvironmentStop) : { jump Stop(); }
}
};
// just wait
Stop(EVoid) {
StopMoving();
wait() {
on (EBegin) : { resume; }
on (EEnvironmentStart) : { jump Activate(); }
}
};
// do actions
DoAction(EVoid) {
while (TRUE) {
WaitOnMarker();
if (m_fWaitTime > 0.0f) {
PlayMarkerAnimation();
autowait(m_fWaitTime);
}
ChangeDefaultAnim();
MarkerParameters();
PlayDefaultAnim();
autocall MoveToMarker() EEnd;
// if no more targets wait forever in last anim (if marker anim exist otherwise in default anim)
if (m_penTarget==NULL || ((CEnvironmentMarker&)*m_penTarget).m_penTarget==NULL) {
autowait();
}
}
};
/************************************************************
* M A I N L O O P *
************************************************************/
// main loop
MainLoop(EVoid) {
autocall Stop() EEnd;
// destroy player watcher
m_penWatcher->SendEvent(EEnd());
// cease to exist
Destroy();
return;
};
Main() {
// initialize
Initialize();
// wait until game starts
autowait(FRnd()*2.0f+1.0f);
// initialize watcher
if (m_bUseWatcher) {
InitializeWatcher(m_fWatcherFrequency);
}
m_strDescription = "Environment base";
jump MainLoop();
};
};

View File

@ -0,0 +1,92 @@
901
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
class CEnvironmentMarker: CMarker {
name "Environment Marker";
thumbnail "Thumbnails\\EnvironmentMarker.tbn";
properties:
1 FLOAT m_fWaitTime "Wait time" 'W' = 0.0f, // time to wait (or do anything until go to another marker)
2 FLOAT m_fRandomTime "Random time" 'E' = 0.0f, // random time to wait (or do anything until go to another marker)
3 RANGE m_fMarkerRange "Marker range" 'R' = 5.0f, // range around marker (marker doesn't have to be hit directly)
4 BOOL m_bFixedAnimLength "Fixed anim length" 'F' = FALSE, // fixed anim length (like play once)
5 BOOL m_bChangeDefaultAnim "Change default anim" 'C' = FALSE, // change default anim
6 FLOAT m_fMoveSpeed "Move speed" 'V' = -1.0f, // moving speed
7 FLOAT m_fRotateSpeed "Rotate speed" 'B' = -1.0f, // rotate speed
// for browsing animations on marker for base environment model
20 CTFileName m_fnMdl "Model" 'M' = CTFILENAME("Models\\Editor\\Axis.mdl"),
21 ANIMATION m_iAnim "Animation" 'A' =0,
22 CModelObject m_moAnimData,
components:
1 model MODEL_MARKER "Models\\Editor\\EnvironmentMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\EnvironmentMarker.tex"
functions:
/* Check if entity is moved on a route set up by its targets. */
BOOL MovesByTargetedRoute(CTString &strTargetProperty) const {
strTargetProperty = "Target";
return TRUE;
};
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const {
fnmMarkerClass = CTFILENAME("Classes\\EnvironmentMarker.ecl");
strTargetProperty = "Target";
return TRUE;
};
/* Get anim data for given animation property - return NULL for none. */
CAnimData *GetAnimData(SLONG slPropertyOffset) {
if(slPropertyOffset==offsetof(CEnvironmentMarker, m_iAnim)) {
return m_moAnimData.GetData();
} else {
return CEntity::GetAnimData(slPropertyOffset);
}
};
// >>> original source from CEntity::SetModel <<<
// set mdoel object
void SetModelObject(void) {
// try to
try {
// load the new model data
m_moAnimData.SetData_t(m_fnMdl);
// if failed
} catch(char *strError) {
strError;
DECLARE_CTFILENAME(fnmDefault, "Models\\Editor\\Axis.mdl");
// try to
try {
// load the default model data
m_moAnimData.SetData_t(fnmDefault);
// if failed
} catch(char *strErrorDefault) {
FatalError(TRANS("Cannot load default model '%s':\n%s"),
(const char*)(CTString&)fnmDefault, strErrorDefault);
}
}
};
procedures:
Main() {
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set model data for anim browser
SetModelObject();
return;
}
};

264
Sources/Entities/Eruptor.es Normal file
View File

@ -0,0 +1,264 @@
213
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/ModelHolder2";
uses "Entities/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,
components:
1 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
functions:
/* 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;
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);
}
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();
}
};

517
Sources/Entities/Eyeman.es Normal file
View File

@ -0,0 +1,517 @@
323
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Eyeman/Eyeman.h"
%}
uses "Entities/EnemyFly";
enum EyemanChar {
0 EYC_SOLDIER "Soldier", // soldier
1 EYC_SERGEANT "Sergeant", // sergeant
};
enum EyemanEnv {
0 EYE_NORMAL "Normal",
1 EYE_LAVA "Lava",
};
%{
// info structure
static EntityInfo eiEyemanBig = {
EIBT_FLESH, 140.0f,
0.0f, 1.4f, 0.0f,
0.0f, 1.0f, 0.0f,
};
static EntityInfo eiEyemanSmall = {
EIBT_FLESH, 120.0f,
0.0f, 1.4f, 0.0f,
0.0f, 1.0f, 0.0f,
};
#define BITE_AIR 3.0f
#define HIT_GROUND 2.0f
#define FIRE_GROUND FLOAT3D(0.75f, 1.5f, -1.25f)
%}
class CEyeman : CEnemyFly {
name "Eyeman";
thumbnail "Thumbnails\\Eyeman.tbn";
properties:
1 enum EyemanChar m_EecChar "Character" 'C' = EYC_SOLDIER, // character
2 BOOL m_bInvisible "Invisible" 'I'=FALSE,
3 enum EyemanEnv m_eeEnv "Environment" 'E' = EYE_NORMAL,
4 BOOL m_bMumbleSoundPlaying = FALSE,
5 CSoundObject m_soMumble,
components:
0 class CLASS_BASE "Classes\\EnemyFly.ecl",
1 model MODEL_EYEMAN "Models\\Enemies\\Eyeman\\Eyeman.mdl",
2 texture TEXTURE_EYEMAN_SOLDIER "Models\\Enemies\\Eyeman\\Eyeman4.tex",
3 texture TEXTURE_EYEMAN_SERGEANT "Models\\Enemies\\Eyeman\\Eyeman5.tex",
5 texture TEXTURE_EYEMAN_LAVA "Models\\Enemies\\Eyeman\\Eyeman6.tex",
4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Eyeman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Eyeman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Eyeman\\Sounds\\Wound.wav",
53 sound SOUND_BITE "Models\\Enemies\\Eyeman\\Sounds\\Bite.wav",
54 sound SOUND_PUNCH "Models\\Enemies\\Eyeman\\Sounds\\Punch.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Eyeman\\Sounds\\Death.wav",
56 sound SOUND_MUMBLE "Models\\Enemies\\Eyeman\\Sounds\\Mumble.wav",
/*
60 model MODEL_EYEMAN_BODY "Models\\Enemies\\Eyeman\\Debris\\Torso.mdl",
61 model MODEL_EYEMAN_HAND "Models\\Enemies\\Eyeman\\Debris\\Arm.mdl",
62 model MODEL_EYEMAN_LEGS "Models\\Enemies\\Eyeman\\Debris\\Leg.mdl",
*/
functions:
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
if (m_bInAir) {
str.PrintF(TRANS("A Gnaar bit %s to death"), (const char*)strPlayerName);
} else {
str.PrintF(TRANS("%s was beaten up by a Gnaar"), (const char*)strPlayerName);
}
return str;
}
void Precache(void) {
CEnemyBase::Precache();
PrecacheSound(SOUND_IDLE );
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_BITE );
PrecacheSound(SOUND_PUNCH);
PrecacheSound(SOUND_DEATH);
PrecacheSound(SOUND_MUMBLE);
};
/* Entity info */
void *GetEntityInfo(void) {
if (m_EecChar==EYC_SERGEANT) {
return &eiEyemanBig;
} else {
return &eiEyemanSmall;
}
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// eyeman can't harm eyeman
if (!IsOfClass(penInflictor, "Eyeman")) {
CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
CEnemyBase::FillEntityStatistics(pes);
switch(m_EecChar) {
case EYC_SERGEANT: { pes->es_strName+=" Sergeant"; } break;
case EYC_SOLDIER : { pes->es_strName+=" Soldier"; } break;
}
if (m_bInvisible) {
pes->es_strName+=" Invisible";
}
return TRUE;
}
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnmSergeant, "Data\\Messages\\Enemies\\EyemanGreen.txt");
static DECLARE_CTFILENAME(fnmSoldier , "Data\\Messages\\Enemies\\EyemanPurple.txt");
switch(m_EecChar) {
default: ASSERT(FALSE);
case EYC_SERGEANT: return fnmSergeant;
case EYC_SOLDIER : return fnmSoldier;
}
};
/* Adjust model shading parameters if needed. */
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
// no shadows for invisibles
if (m_bInvisible) {
colAmbient = C_WHITE;
return FALSE;
} else {
return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
}
}
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
DeactivateMumblingSound();
INDEX iAnim;
if (m_bInAir) {
switch (IRnd()%2) {
case 0: iAnim = EYEMAN_ANIM_MORPHWOUND01; break;
case 1: iAnim = EYEMAN_ANIM_MORPHWOUND02; break;
default: ASSERTALWAYS("Eyeman unknown fly damage");
}
} else {
FLOAT3D vFront;
GetHeadingDirection(0, vFront);
FLOAT fDamageDir = m_vDamage%vFront;
if (Abs(fDamageDir)<=10) {
switch (IRnd()%3) {
case 0: iAnim = EYEMAN_ANIM_WOUND03; break;
case 1: iAnim = EYEMAN_ANIM_WOUND06; break;
case 2: iAnim = EYEMAN_ANIM_WOUND07; break;
}
} else {
if (fDamageDir<0) {
iAnim = EYEMAN_ANIM_FALL01;
} else {
iAnim = EYEMAN_ANIM_FALL02;
}
}
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
DeactivateMumblingSound();
INDEX iAnim;
if (m_bInAir) {
iAnim = EYEMAN_ANIM_MORPHDEATH;
} else {
FLOAT3D vFront;
GetHeadingDirection(0, vFront);
FLOAT fDamageDir = m_vDamage%vFront;
if (fDamageDir<0) {
iAnim = EYEMAN_ANIM_DEATH02;
} else {
iAnim = EYEMAN_ANIM_DEATH01;
}
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// mumbling sounds
void ActivateMumblingSound(void)
{
if (!m_bMumbleSoundPlaying) {
PlaySound(m_soMumble, SOUND_MUMBLE, SOF_3D|SOF_LOOP);
m_bMumbleSoundPlaying = TRUE;
}
}
void DeactivateMumblingSound(void)
{
m_soMumble.Stop();
m_bMumbleSoundPlaying = FALSE;
}
// virtual anim functions
void StandingAnim(void) {
DeactivateMumblingSound();
if (m_bInAir) {
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(EYEMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
}
};
void WalkingAnim(void) {
ActivateMumblingSound();
if (m_bInAir) {
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(EYEMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
}
};
void RunningAnim(void) {
ActivateMumblingSound();
if (m_bInAir) {
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
}
};
void RotatingAnim(void) {
if (m_bInAir) {
StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
}
};
FLOAT AirToGroundAnim(void) {
StartModelAnim(EYEMAN_ANIM_MORPHUP, 0);
return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHUP));
};
FLOAT GroundToAirAnim(void) {
StartModelAnim(EYEMAN_ANIM_MORPHDOWN, 0);
return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHDOWN));
};
void ChangeCollisionToAir() {
ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_AIR);
};
void ChangeCollisionToGround() {
ChangeCollisionBoxIndexWhenPossible(EYEMAN_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);
};
/************************************************************
* BLOW UP FUNCTIONS *
************************************************************/
// spawn body parts
/*void BlowUp(void)
{
// get your size
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length());
vNormalizedDamage /= Sqrt(vNormalizedDamage.Length());
vNormalizedDamage *= 0.75f;
FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute);
// spawn debris
Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f);
INDEX iTextureID = TEXTURE_EYEMAN_SOLDIER;
if (m_EecChar==EYC_SERGEANT)
{
iTextureID = TEXTURE_EYEMAN_SERGEANT;
}
Debris_Spawn(this, this, MODEL_EYEMAN_BODY, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_EYEMAN_LEGS, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
// hide yourself (must do this after spawning debris)
SwitchToEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
};*/
/************************************************************
* MOVING FUNCTIONS *
************************************************************/
// check whether may move while attacking
BOOL MayMoveToAttack(void)
{
if (m_bInAir) {
return WouldNotLeaveAttackRadius();
} else {
return CEnemyBase::MayMoveToAttack();
}
}
// must be more relaxed about hitting then usual enemies
BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) {
if (IsInPlaneFrustum(penTarget, fCosAngle)) {
return IsVisibleCheckAll(penTarget);
}
return FALSE;
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
FlyHit(EVoid) : CEnemyFly::FlyHit {
if (CalcDist(m_penEnemy) > BITE_AIR) {
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
return EReturn();
}
StartModelAnim(EYEMAN_ANIM_MORPHATTACK, 0);
StopMoving();
PlaySound(m_soSound, SOUND_BITE, SOF_3D);
// damage enemy
autowait(0.4f);
// damage enemy
if (CalcDist(m_penEnemy) < BITE_AIR) {
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
// spawn blood cloud
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_BLOODEXPLODE;
eSpawnEffect.vStretch = FLOAT3D(1,1,1);
CPlacement3D plOne = GetPlacement();
GetEntityPointRatio(
FLOAT3D(Lerp(-0.2f, +0.2f, FRnd()), Lerp(-0.2f, +0.2f, FRnd()), -1.0f),
plOne.pl_PositionVector);
CEntityPointer penBloodCloud = CreateEntity( plOne, CLASS_BASIC_EFFECT);
penBloodCloud->Initialize( eSpawnEffect);
}
autowait(0.24f);
StandingAnim();
return EReturn();
};
GroundHit(EVoid) : CEnemyFly::GroundHit {
if (CalcDist(m_penEnemy) > HIT_GROUND) {
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
return EReturn();
}
StartModelAnim(EYEMAN_ANIM_ATTACK02, 0);
StopMoving();
// damage enemy
autowait(0.2f);
// damage enemy
if (CalcDist(m_penEnemy) < HIT_GROUND) {
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
}
autowait(0.3f);
// damage enemy
if (CalcDist(m_penEnemy) < HIT_GROUND) {
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection);
PlaySound(m_soSound, SOUND_PUNCH, SOF_3D);
}
autowait(0.4f);
StandingAnim();
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_EecChar==EYC_SERGEANT) {
SetHealth(90.0f);
m_fMaxHealth = 90.0f;
// damage/explode properties
m_fBlowUpAmount = 130.0f;
m_fBodyParts = 5;
m_fBlowUpSize = 2.5f;
m_fDamageWounded = 40.0f;
} else {
SetHealth(60.0f);
m_fMaxHealth = 60.0f;
// damage/explode properties
m_fBlowUpAmount = 100.0f;
m_fBodyParts = 5;
m_fBlowUpSize = 2.0f;
m_fDamageWounded = 25.0f;
}
en_fDensity = 2000.0f;
if (m_EeftType == EFT_GROUND_ONLY) {
en_tmMaxHoldBreath = 5.0f;
} else {
en_tmMaxHoldBreath = 30.0f;
}
// set your appearance
SetModel(MODEL_EYEMAN);
if (m_EecChar==EYC_SERGEANT) {
SetModelMainTexture(TEXTURE_EYEMAN_SERGEANT);
GetModelObject()->StretchModel(FLOAT3D(1.3f, 1.3f, 1.3f));
ModelChangeNotify();
m_iScore = 1000;
} else {
m_iScore = 500;
if (m_eeEnv == EYE_LAVA) {
SetModelMainTexture(TEXTURE_EYEMAN_LAVA);
} else {
SetModelMainTexture(TEXTURE_EYEMAN_SOLDIER);
}
GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
ModelChangeNotify();
}
if (m_bInvisible) {
GetModelObject()->mo_colBlendColor = C_WHITE|0x25;
m_iScore*=2;
}
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = FRnd()*10.0f + 500.0f;
if (m_EecChar==EYC_SERGEANT) {
m_fAttackRunSpeed = FRnd()*2.0f + 10.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 10.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
} else {
m_fAttackRunSpeed = FRnd()*2.0f + 9.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 9.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
}
// setup attack distances
m_fAttackDistance = 100.0f;
m_fCloseDistance = 3.5f;
m_fStopDistance = 1.5f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 0.5f;
m_fIgnoreRange = 200.0f;
// fly moving properties
m_fFlyWalkSpeed = FRnd()*2.0f + 3.0f;
m_aFlyWalkRotateSpeed = FRnd()*20.0f + 600.0f;
if (m_EecChar==EYC_SERGEANT) {
m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f;
m_aFlyAttackRotateSpeed = FRnd()*25 + 350.0f;
m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f;
m_aFlyCloseRotateSpeed = FRnd()*50 + 400.0f;
} else {
m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f;
m_aFlyAttackRotateSpeed = FRnd()*25 + 300.0f;
m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f;
m_aFlyCloseRotateSpeed = FRnd()*50 + 300.0f;
}
m_fGroundToAirSpeed = 2.5f;
m_fAirToGroundSpeed = 2.5f;
m_fAirToGroundMin = 0.1f;
m_fAirToGroundMax = 0.1f;
m_fFlyHeight = 1.0f;
// attack properties - CAN BE SET
m_fFlyAttackDistance = 100.0f;
m_fFlyCloseDistance = 10.0f;
m_fFlyStopDistance = 1.5f;
m_fFlyAttackFireTime = 2.0f;
m_fFlyCloseFireTime = 0.5f;
m_fFlyIgnoreRange = 200.0f;
m_soMumble.Set3DParameters(25.0f, 0.0f, 1.0f, 1.0f);
// continue behavior in base class
jump CEnemyFly::MainLoop();
};
};

335
Sources/Entities/Fish.es Normal file
View File

@ -0,0 +1,335 @@
337
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Fish/Fish.h"
%}
uses "Entities/EnemyDive";
%{
static EntityInfo eiFish = {
EIBT_FLESH, 100.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
#define DISTANCE_ELECTRICITY 8.0f
%}
class CFish : CEnemyDive {
name "Fish";
thumbnail "Thumbnails\\Fish.tbn";
properties:
0 BOOL m_bAttackingByElectricity = FALSE,
1 FLOAT m_tmElectricityTimeStart = 0.0f,
components:
0 class CLASS_BASE "Classes\\EnemyDive.ecl",
1 model MODEL_FISH "Models\\Enemies\\Fish\\Fish.mdl",
2 texture TEXTURE_FISH "Models\\Enemies\\Fish\\Fish1.tex",
3 model MODEL_GLOW "Models\\Enemies\\Fish\\Glow.mdl",
4 texture TEXTURE_GLOW "Models\\Enemies\\Fish\\Glow.tex",
5 texture TEXTURE_SPECULAR "Models\\SpecularTextures\\Medium.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Fish\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Fish\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Fish\\Sounds\\Wound.wav",
53 sound SOUND_DEATH "Models\\Enemies\\Fish\\Sounds\\Death.wav",
54 sound SOUND_ATTACK "Models\\Enemies\\Fish\\Sounds\\Attack.wav",
55 sound SOUND_WOUNDAIR "Models\\Enemies\\Fish\\Sounds\\WoundAir.wav",
56 sound SOUND_DEATHAIR "Models\\Enemies\\Fish\\Sounds\\DeathAir.wav",
functions:
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
str.PrintF(TRANS("%s was electrocuted by a fish"),(const char*) strPlayerName);
return str;
}
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Fish.txt");
return fnm;
};
void Precache(void) {
CEnemyBase::Precache();
PrecacheModel(MODEL_GLOW );
PrecacheTexture(TEXTURE_GLOW);
PrecacheSound(SOUND_IDLE);
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_DEATH);
PrecacheSound(SOUND_WOUNDAIR);
PrecacheSound(SOUND_DEATHAIR);
PrecacheSound(SOUND_ATTACK);
};
/* Entity info */
void *GetEntityInfo(void)
{
return &eiFish;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
if (dmtType==DMT_DROWNING) {
//en_tmMaxHoldBreath = -5.0f;
fDamageAmmount/=2.0f;
}
// fish can't harm fish
if (!IsOfClass(penInflictor, "Fish")) {
CEnemyDive::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage)
{
m_bAttackingByElectricity = FALSE;
INDEX iAnim = FISH_ANIM_WOUND;
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
if (!m_bInLiquid) {
return AnimForDamage(10.0f);
}
INDEX iAnim;
switch (IRnd()%3) {
default: iAnim = FISH_ANIM_DEATH; break;
case 0: iAnim = FISH_ANIM_DEATH; break;
case 1: iAnim = FISH_ANIM_DEATH02; break;
case 2: iAnim = FISH_ANIM_DEATH03; break;
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void)
{
m_bAttackingByElectricity = FALSE;
en_fDensity = 500.0f;
};
void RenderParticles(void)
{
if( m_bAttackingByElectricity && m_penEnemy!=NULL)
{
// render one lightning toward enemy
FLOAT3D vSource = GetPlacement().pl_PositionVector;
FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector;
FLOAT3D vDirection = (vTarget-vSource).Normalize();
Particles_Ghostbuster(vSource, vTarget, 32, 1.0f);
// random lightnings arround
for( INDEX i=0; i<4; i++)
{
FLOAT3D vDirection = vSource;
vDirection(1) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f;
vDirection(2) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f;
vDirection(3) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f;
Particles_Ghostbuster(vSource, vDirection, 32, 1.0f);
}
}
CEnemyBase::RenderParticles();
}
// virtual anim functions
void StandingAnim(void)
{
StartModelAnim(FISH_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void)
{
if (m_bInLiquid) {
StartModelAnim(FISH_ANIM_SWIM, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(FISH_ANIM_WOUND, AOF_LOOPING|AOF_NORESTART);
}
};
void RunningAnim(void)
{
WalkingAnim();
};
void RotatingAnim(void)
{
WalkingAnim();
};
// virtual sound functions
void IdleSound(void)
{
PlaySound(m_soSound, SOUND_IDLE, SOF_3D|SOF_NOFILTER);
};
void SightSound(void)
{
PlaySound(m_soSound, SOUND_SIGHT, SOF_3D|SOF_NOFILTER);
};
void WoundSound(void)
{
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_WOUND, SOF_3D|SOF_NOFILTER);
} else {
PlaySound(m_soSound, SOUND_WOUNDAIR, SOF_3D|SOF_NOFILTER);
}
};
void DeathSound(void)
{
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_DEATH, SOF_3D|SOF_NOFILTER);
} else {
PlaySound(m_soSound, SOUND_DEATHAIR, SOF_3D|SOF_NOFILTER);
}
};
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
FLOAT fTimePassed = _pTimer->GetLerpedCurrentTick()-m_tmElectricityTimeStart;
if( m_bAttackingByElectricity && (fTimePassed>0))
{
FLOAT fDieFactor = 1.0f;
if( fTimePassed > 0.25f)
{
// calculate light dying factor
fDieFactor = 1.0-(ClampUp(fTimePassed-0.25f,0.5f)/0.5f);
}
// adjust light fx
FLOAT fR = 0.7f+0.1f*(FLOAT(rand())/RAND_MAX);
FLOAT fG = 0.7f+0.2f*(FLOAT(rand())/RAND_MAX);
FLOAT fB = 0.7f+0.3f*(FLOAT(rand())/RAND_MAX);
colAmbient = RGBToColor( fR*128*fDieFactor, fG*128*fDieFactor, fB*128*fDieFactor);
colLight = C_WHITE;
return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
}
return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient);
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
DiveHit(EVoid) : CEnemyDive::DiveHit
{
if (CalcDist(m_penEnemy) > DISTANCE_ELECTRICITY)
{
// swim to enemy
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
return EReturn();
}
// wait to allow enemy to go aoutside bite range
autowait(0.6f);
m_bAttackingByElectricity = TRUE;
m_tmElectricityTimeStart = _pTimer->CurrentTick();
AddAttachmentToModel(this, *GetModelObject(), FISH_ATTACHMENT_GLOW, MODEL_GLOW, TEXTURE_GLOW, 0, 0, 0);
CModelObject &moGlow = GetModelObject()->GetAttachmentModel(FISH_ATTACHMENT_GLOW)->amo_moModelObject;
moGlow.StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f));
// bite
StartModelAnim(FISH_ANIM_ATTACK, 0);
PlaySound(m_soSound, SOUND_ATTACK, SOF_3D|SOF_NOFILTER);
if (CalcDist(m_penEnemy)<DISTANCE_ELECTRICITY)
{
// damage enemy
InflictRangeDamage(this, DMT_CLOSERANGE, 15.0f, GetPlacement().pl_PositionVector, 1.0f, DISTANCE_ELECTRICITY);
// push target away
FLOAT3D vSpeed;
GetHeadingDirection(0.0f, vSpeed);
vSpeed = vSpeed * 30.0f;
KickEntity(m_penEnemy, vSpeed);
}
autowait(0.5f);
m_bAttackingByElectricity = FALSE;
GetModelObject()->RemoveAttachmentModel(FISH_ATTACHMENT_GLOW);
StandingAnim();
autowait(0.2f + FRnd()/3);
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit
{
jump DiveHit();
}
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
// fish must not go upstairs, or it will get out of water
SetPhysicsFlags((EPF_MODEL_WALKING|EPF_HASGILLS)&~EPF_ONBLOCK_CLIMBORSLIDE|EPF_ONBLOCK_SLIDE);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetHealth(30.0f);
m_fMaxHealth = 30.0f;
en_tmMaxHoldBreath = 15.0f;
en_fDensity = 1000.0f;
m_EedtType = EDT_GROUND_DIVE;
// set your appearance
SetModel(MODEL_FISH);
SetModelMainTexture(TEXTURE_FISH);
SetModelSpecularTexture(TEXTURE_SPECULAR);
// rotation speeds
m_fDiveWalkSpeed = 15.0f;
m_fDiveAttackRunSpeed = 20.0f;
m_fDiveCloseRunSpeed = 25.0f;
m_fWalkSpeed = 15.0f;
m_aWalkRotateSpeed = 900.0f;
m_fAttackRunSpeed = 10.0f;
m_fCloseRunSpeed = 12.0f;
// translation speeds
m_aDiveWalkRotateSpeed = 360.0f;
m_aDiveAttackRotateSpeed = 1800.0f;
m_aDiveCloseRotateSpeed = 3600.0f;
// distances
m_fDiveIgnoreRange = 200.0f;
m_fDiveAttackDistance = 100.0f;
m_fDiveCloseDistance = 15.0f;
m_fDiveStopDistance = 2.0f;
// frequencies
m_fDiveAttackFireTime = 0.0f;
m_fDiveCloseFireTime = 0.0f;
// damage/explode properties
m_fBlowUpAmount = 80.0f;
m_fBodyParts = 2;
m_fDamageWounded = 1.0f;
m_iScore = 500;
{
// translation speeds
m_aWalkRotateSpeed = 360.0f;
m_aAttackRotateSpeed = 1800.0f;
m_aCloseRotateSpeed = 3600.0f;
// distances
m_fIgnoreRange = 200.0f;
m_fAttackDistance = 100.0f;
m_fCloseDistance = 15.0f;
m_fStopDistance = 2.0f;
// frequencies
m_fAttackFireTime = 0.0f;
m_fCloseFireTime = 0.0f;
}
// set stretch factors for height and width
GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f));
ModelChangeNotify();
en_fAcceleration = 200.0f;
en_fDeceleration = 200.0f;
// continue behavior in base class
jump CEnemyDive::MainLoop();
};
};

350
Sources/Entities/Fishman.es Normal file
View File

@ -0,0 +1,350 @@
328
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Fishman/fishman.h"
%}
uses "Entities/EnemyDive";
%{
static EntityInfo eiFishmanGround = {
EIBT_FLESH, 100.0f,
0.0f, 1.4f, 0.0f,
0.0f, 1.0f, 0.0f,
};
static EntityInfo eiFishmanLiquid = {
EIBT_FLESH, 33.3f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
#define FIRE_WATER FLOAT3D(0.0f, 0.3f, -1.1f)
#define FIRE_GROUND FLOAT3D(0.0f, 0.8f, -1.25f)
#define SPEAR_HIT 1.75f
%}
class CFishman : CEnemyDive {
name "Fishman";
thumbnail "Thumbnails\\Fishman.tbn";
properties:
components:
0 class CLASS_BASE "Classes\\EnemyDive.ecl",
1 model MODEL_FISHMAN "Models\\Enemies\\Fishman\\Fishman.mdl",
2 texture TEXTURE_FISHMAN "Models\\Enemies\\Fishman\\Fishman.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE_WATER "Models\\Enemies\\Fishman\\Sounds\\IdleWater.wav",
51 sound SOUND_IDLE_GROUND "Models\\Enemies\\Fishman\\Sounds\\IdleGround.wav",
52 sound SOUND_SIGHT_WATER "Models\\Enemies\\Fishman\\Sounds\\SightWater.wav",
53 sound SOUND_SIGHT_GROUND "Models\\Enemies\\Fishman\\Sounds\\SightGround.wav",
54 sound SOUND_WOUND_WATER "Models\\Enemies\\Fishman\\Sounds\\WoundWater.wav",
55 sound SOUND_WOUND_GROUND "Models\\Enemies\\Fishman\\Sounds\\WoundGround.wav",
56 sound SOUND_DEATH_WATER "Models\\Enemies\\Fishman\\Sounds\\DeathWater.wav",
57 sound SOUND_DEATH_GROUND "Models\\Enemies\\Fishman\\Sounds\\DeathGround.wav",
58 sound SOUND_FIRE "Models\\Enemies\\Fishman\\Sounds\\Fire.wav",
59 sound SOUND_KICK "Models\\Enemies\\Fishman\\Sounds\\Kick.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
if (m_bInLiquid) {
return &eiFishmanLiquid;
} else {
return &eiFishmanGround;
}
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// fishman can't harm fishman
if (!IsOfClass(penInflictor, "Fishman")) {
CEnemyDive::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
if (m_bInLiquid) {
switch (IRnd()%2) {
case 0: iAnim = FISHMAN_ANIM_WATERWOUND01; break;
case 1: iAnim = FISHMAN_ANIM_WATERWOUND02; break;
default: ASSERTALWAYS("Fishman unknown liquid damage");
}
} else {
switch (IRnd()%3) {
case 0: iAnim = FISHMAN_ANIM_GROUNDWOUND03; break;
case 1: iAnim = FISHMAN_ANIM_GROUNDWOUND04; break;
case 2: iAnim = FISHMAN_ANIM_GROUNDWOUND05; break;
default: ASSERTALWAYS("Fishman unknown ground damage");
}
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
if (m_bInLiquid) {
iAnim = FISHMAN_ANIM_WATERDEATH;
} else {
iAnim = FISHMAN_ANIM_GROUNDDEATH;
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
if (m_bInLiquid) {
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_DEATH_WATER);
} else {
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_DEATH_GROUND);
}
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
if (m_bInLiquid) {
StartModelAnim(FISHMAN_ANIM_WATERSTAND, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(FISHMAN_ANIM_GROUNDSTAND, AOF_LOOPING|AOF_NORESTART);
}
};
void WalkingAnim(void) {
if (m_bInLiquid) {
StartModelAnim(FISHMAN_ANIM_WATERSWIM02, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(FISHMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
}
};
void RunningAnim(void) {
if (m_bInLiquid) {
StartModelAnim(FISHMAN_ANIM_WATERSWIM01, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(FISHMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART);
}
};
void RotatingAnim(void) {
if (m_bInLiquid) {
StartModelAnim(FISHMAN_ANIM_WATERSWIM02, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(FISHMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART);
}
};
void ChangeCollisionToLiquid() {
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_WATER);
};
void ChangeCollisionToGround() {
ChangeCollisionBoxIndexWhenPossible(FISHMAN_COLLISION_BOX_GROUND);
};
// virtual sound functions
void IdleSound(void) {
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_IDLE_WATER , SOF_3D);
} else {
PlaySound(m_soSound, SOUND_IDLE_GROUND, SOF_3D);
}
};
void SightSound(void) {
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_SIGHT_WATER , SOF_3D);
} else {
PlaySound(m_soSound, SOUND_SIGHT_GROUND, SOF_3D);
}
};
void WoundSound(void) {
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_WOUND_WATER , SOF_3D);
} else {
PlaySound(m_soSound, SOUND_WOUND_GROUND, SOF_3D);
}
};
void DeathSound(void) {
if (m_bInLiquid) {
PlaySound(m_soSound, SOUND_DEATH_WATER , SOF_3D);
} else {
PlaySound(m_soSound, SOUND_DEATH_GROUND, SOF_3D);
}
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
DiveFire(EVoid) : CEnemyDive::DiveFire {
// fire projectile
StartModelAnim(FISHMAN_ANIM_WATERATTACK02, 0);
autowait(0.4f);
ShootProjectile(PRT_FISHMAN_FIRE, FIRE_WATER, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.95f);
StandingAnim();
autowait(FRnd()/3 + _pTimer->TickQuantum);
return EReturn();
};
DiveHit(EVoid) : CEnemyDive::DiveHit {
if (CalcDist(m_penEnemy) > SPEAR_HIT) {
// run to enemy
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
return EReturn();
}
// attack with spear
StartModelAnim(FISHMAN_ANIM_WATERATTACK01, 0);
// to left hit
autowait(0.5f);
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 5.0f, FLOAT3D(0, 0, 0), vDirection);
// push target away
FLOAT3D vSpeed;
GetHeadingDirection(0.0f, vSpeed);
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
autowait(0.5f);
StandingAnim();
autowait(0.2f + FRnd()/3);
return EReturn();
};
Fire(EVoid) : CEnemyBase::Fire {
// wait anim end
if (!GetModelObject()->IsAnimFinished()) {
autowait(GetModelObject()->GetCurrentAnimLength() - GetModelObject()->GetPassedTime());
}
// fire projectile
StartModelAnim(FISHMAN_ANIM_GROUNDATTACK02, 0);
autowait(0.3f);
ShootProjectile(PRT_FISHMAN_FIRE, FIRE_GROUND, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.4f);
StandingAnim();
autowait(FRnd()/3 + _pTimer->TickQuantum);
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit {
if (CalcDist(m_penEnemy) > SPEAR_HIT) {
// run to enemy
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
return EReturn();
}
// wait anim end
if (!GetModelObject()->IsAnimFinished()) {
autowait(GetModelObject()->GetCurrentAnimLength() - GetModelObject()->GetPassedTime());
}
// attack with spear
StartModelAnim(FISHMAN_ANIM_GROUNDATTACKLOOP, 0);
// to left hit
autowait(0.5f);
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 2.5f, FLOAT3D(0, 0, 0), vDirection);
// push target left
FLOAT3D vSpeed;
GetHeadingDirection(90.0f, vSpeed);
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
autowait(0.5f);
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
if (CalcDist(m_penEnemy)<SPEAR_HIT) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 2.5f, FLOAT3D(0, 0, 0), vDirection);
// push target right
FLOAT3D vSpeed;
GetHeadingDirection(-90.0f, vSpeed);
vSpeed = vSpeed * 5.0f;
KickEntity(m_penEnemy, vSpeed);
}
autowait(0.6f);
StandingAnim();
autowait(0.2f + FRnd()/3);
return EReturn();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS|EPF_HASGILLS);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetHealth(30.0f);
m_fMaxHealth = 30.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 1000.0f;
// set your appearance
SetModel(MODEL_FISHMAN);
SetModelMainTexture(TEXTURE_FISHMAN);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = FRnd()*10.0f + 500.0f;
m_fAttackRunSpeed = FRnd()*0.5f + 5.0f;
m_aAttackRotateSpeed = FRnd()*50 + 245.0f;
m_fCloseRunSpeed = FRnd()*0.5f + 5.0f;
m_aCloseRotateSpeed = FRnd()*50 + 245.0f;
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 5.0f;
m_fStopDistance = 0.0f;
m_fAttackFireTime = 3.0f;
m_fCloseFireTime = 2.0f;
m_fIgnoreRange = 200.0f;
// fly moving properties
m_fDiveWalkSpeed = FRnd() + 3.0f;
m_aDiveWalkRotateSpeed = FRnd()*10.0f + 500.0f;
m_fDiveAttackRunSpeed = FRnd()*4.0f + 14.0f;
m_aDiveAttackRotateSpeed = FRnd()*25 + 500.0f;
m_fDiveCloseRunSpeed = FRnd()*2.0f + 8.0f;
m_aDiveCloseRotateSpeed = FRnd()*50 + 800.0f;
// attack properties
m_fDiveAttackDistance = 50.0f;
m_fDiveCloseDistance = 3.0f;
m_fDiveStopDistance = 0.0f;
m_fDiveAttackFireTime = 3.0f;
m_fDiveCloseFireTime = 2.0f;
m_fDiveIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 60.0f;
m_fBodyParts = 4;
m_fDamageWounded = 15.0f;
m_iScore = 500;
// continue behavior in base class
jump CEnemyDive::MainLoop();
};
};

182
Sources/Entities/Flame.es Normal file
View File

@ -0,0 +1,182 @@
504
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Light";
// input parameter for flame
event EFlame {
CEntityPointer penOwner, // entity which owns it
CEntityPointer penAttach, // entity on which flame is attached (his parent)
};
%{
void CFlame_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheModel(MODEL_FLAME);
pdec->PrecacheTexture(TEXTURE_FLAME);
pdec->PrecacheSound(SOUND_FLAME);
}
%}
class CFlame : CMovableModelEntity {
name "Flame";
thumbnail "";
features "ImplementsOnPrecache", "CanBePredictable";
properties:
1 CEntityPointer m_penOwner, // entity which owns it
2 CEntityPointer m_penAttach, // entity on which flame is attached (his parent)
5 BOOL m_bLoop = FALSE, // internal for loops
10 CSoundObject m_soEffect, // sound channel
{
CLightSource m_lsLightSource;
}
components:
1 class CLASS_LIGHT "Classes\\Light.ecl",
// ********* FLAME *********
10 model MODEL_FLAME "Models\\Effects\\Flame\\Flame.mdl",
//"Models\\Weapons\\Flamer\\Projectile\\Invisible.mdl",
11 texture TEXTURE_FLAME "Models\\Effects\\Flame\\Flame.tex",
12 sound SOUND_FLAME "Sounds\\Fire\\Fire4.wav",
functions:
// add to prediction any entities that this entity depends on
void AddDependentsToPrediction(void)
{
m_penOwner->AddToPrediction();
}
// postmoving
void PostMoving(void) {
CMovableModelEntity::PostMoving();
// if no air
CContentType &ctDn = GetWorld()->wo_actContentTypes[en_iDnContent];
// stop existing
if (!(ctDn.ct_ulFlags&CTF_BREATHABLE_LUNGS)) {
SendEvent(EEnd());
}
// never remove from list of movers
en_ulFlags &= ~ENF_INRENDERING;
// not moving in fact, only moving with its parent
en_plLastPlacement = en_plPlacement;
};
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CRationalEntity::Read_t(istr);
SetupLightSource();
}
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
if (!IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
}
// Setup light source
void SetupLightSource(void)
{
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC;
lsNew.ls_colColor = C_dYELLOW;
lsNew.ls_rFallOff = 2.0f;
lsNew.ls_rHotSpot = 0.2f;
lsNew.ls_plftLensFlare = NULL;
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = NULL;
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
}
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
// --->>> MAIN
Main(EFlame ef) {
// attach to parent (another entity)
ASSERT(ef.penOwner!=NULL);
ASSERT(ef.penAttach!=NULL);
m_penOwner = ef.penOwner;
m_penAttach = ef.penAttach;
SetParent(ef.penAttach);
// initialization
InitAsModel();
SetPhysicsFlags(EPF_MODEL_FLYING);
SetCollisionFlags(ECF_FLAME);
SetFlags(GetFlags() | ENF_SEETHROUGH);
// if parent is model
if (m_penAttach->GetRenderType()==CEntity::RT_MODEL) {
// stretch to its size
FLOATaabbox3D box;
m_penAttach->GetBoundingBox(box);
GetModelObject()->StretchModel(box.Size());
}
ModelChangeNotify();
SetModel(MODEL_FLAME);
SetModelMainTexture(TEXTURE_FLAME);
// play the burning sound
m_soEffect.Set3DParameters(5.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soEffect, SOUND_FLAME, SOF_3D|SOF_LOOP);
// setup light source
SetupLightSource();
// must always be in movers, to find sector content type
AddToMovers();
// burning damage
SpawnReminder(this, 7.5f, 0);
m_bLoop = TRUE;
while(m_bLoop) {
wait(0.25f) {
// damage to parent
on (EBegin) : {
// if parent does not exist anymore
if (m_penAttach==NULL || (m_penAttach->GetFlags()&ENF_DELETED)) {
// stop existing
m_bLoop = FALSE;
stop;
}
// inflict damage to parent
m_penAttach->InflictDirectDamage(m_penAttach, m_penOwner, DMT_BURNING, 1.0f, FLOAT3D(0, 0, 0), -en_vGravityDir);
resume;
}
on (EFlame ef) : {
m_penOwner = ef.penOwner;
resume;
};
on (ETimer) : { stop; }
on (EReminder) : {
m_bLoop = FALSE;
stop;
}
on (EEnd) : {
m_bLoop = FALSE;
stop;
}
}
}
// cease to exist
Destroy();
return;
}
};

View File

@ -0,0 +1,142 @@
215
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
enum FogAttenuationType {
0 FA_LINEAR "Linear",
1 FA_EXP "Exp",
2 FA_EXP2 "Exp2",
};
enum FogGraduationType2 {
0 FG_CONSTANT "Constant",
1 FG_LINEAR "Linear",
2 FG_EXP "Exp",
};
class CFogMarker: CMarker {
name "Fog Marker";
thumbnail "Thumbnails\\FogMarker.tbn";
features "IsImportant";
properties:
1 FLOAT m_fDepth "Depth" 'E' = 10.0f,
2 FLOAT m_fAbove "Above" 'O' = 20.0f,
3 FLOAT m_fBelow "Below" 'B' = 20.0f,
4 FLOAT m_fFar "Far" 'F' = 100.0f,
10 enum FogAttenuationType m_faType "Attenuation Type" 'A' =FA_EXP,
11 FLOAT m_fDensity "Density" 'D' = 0.1f,
12 enum FogGraduationType2 m_fgType "Graduation Type" 'G' =FG_CONSTANT,
13 FLOAT m_fGraduation "Graduation" 'R' = 0.1f,
// for indirect density calculation
14 BOOL m_bDensityDirect "Density Direct" = TRUE,
15 FLOAT m_fDensityPercentage "DensityPercentage" = 0.95f,
16 FLOAT m_fDensityDistance "DensityDistance" = 10.0f,
// for indirect graduation calculation
17 BOOL m_bGraduationDirect "Graduation Direct" = TRUE,
18 FLOAT m_fGraduationPercentage "GraduationPercentage" = 0.95f,
19 FLOAT m_fGraduationDistance "GraduationDistance" = 10.0f,
22 INDEX m_iSizeL "Size Distance" 'S' = 32,
23 INDEX m_iSizeH "Size Depth" 'I' = 16,
24 COLOR m_colColor "Color" 'C' = (C_WHITE|CT_OPAQUE),
components:
1 model MODEL_MARKER "Models\\Editor\\Fog.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Fog.tex"
functions:
/* Get fog type name, return empty string if not used. */
const CTString &GetFogName(void)
{
return m_strName;
}
/* Get fog. */
void GetFog(class CFogParameters &fpFog)
{
const FLOATmatrix3D &m = GetRotationMatrix();
fpFog.fp_vFogDir(1) = m(1,2);
fpFog.fp_vFogDir(2) = m(2,2);
fpFog.fp_vFogDir(3) = m(3,2);
FLOAT fPos = fpFog.fp_vFogDir%GetPlacement().pl_PositionVector;
fpFog.fp_colColor = m_colColor;
fpFog.fp_atType = (AttenuationType) m_faType;
fpFog.fp_fDensity = m_fDensity;
fpFog.fp_fgtType = (FogGraduationType) m_fgType;
fpFog.fp_fGraduation = m_fGraduation;
fpFog.fp_fH0 = fPos-m_fDepth-m_fBelow;
fpFog.fp_fH1 = fPos-m_fDepth;
fpFog.fp_fH2 = fPos;
fpFog.fp_fH3 = fPos+m_fAbove;
fpFog.fp_fFar = m_fFar;
fpFog.fp_iSizeH = m_iSizeH;
fpFog.fp_iSizeL = m_iSizeL;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if (m_strName=="Marker") {
m_strName = "Fog marker";
}
// if density is calculated indirectly
if (!m_bDensityDirect) {
// calculate density to have given percentage at given distance
switch(m_faType) {
case FA_LINEAR:
m_fDensity = m_fDensityPercentage/m_fDensityDistance;
break;
case FA_EXP:
m_fDensity = -log(1-m_fDensityPercentage)/m_fDensityDistance;
break;
case FA_EXP2:
m_fDensity = Sqrt(-log(1-m_fDensityPercentage))/m_fDensityDistance;
break;
}
}
// if graduation is calculated indirectly
if (!m_bGraduationDirect) {
// calculate graduation to have given percentage at given depth
switch(m_fgType) {
case FG_LINEAR:
m_fGraduation = m_fGraduationPercentage/m_fGraduationDistance;
break;
case FG_EXP:
m_fGraduation = -log(1-m_fGraduationPercentage)/m_fGraduationDistance;
break;
}
}
// clamp values to valid ranges
m_fDensity = ClampDn(m_fDensity, 1E-6f);
m_fDepth = ClampDn(m_fDepth , 0.001f);
m_fAbove = ClampDn(m_fAbove , 0.001f);
m_fBelow = ClampDn(m_fBelow , 0.001f);
m_fFar = ClampDn(m_fFar, 0.001f);
m_iSizeL = 1<<INDEX(Log2(m_iSizeL));
m_iSizeH = 1<<INDEX(Log2(m_iSizeH));
m_iSizeL= Clamp(m_iSizeL, INDEX(2), INDEX(256));
m_iSizeH= Clamp(m_iSizeH, INDEX(2), INDEX(256));
return;
}
};

View File

@ -0,0 +1,272 @@
/*
* This file is generated by Entity Class Compiler, (c) CroTeam 1997-98
*/
#line 2 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
#include "Entities/StdH/StdH.h"
#include <Entities/GhostBusterRay.h>
#include <Entities/GhostBusterRay_tables.h>
CEntityEvent *EGhostBusterRay::MakeCopy(void) { CEntityEvent *peeCopy = new EGhostBusterRay(*this); return peeCopy;}
EGhostBusterRay::EGhostBusterRay() : CEntityEvent(EVENTCODE_EGhostBusterRay) {;
ClearToDefault(penOwner);
};
#line 16 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
#define HIT_DISTANCE 50.0f // ray hit distance
#define HIT_DAMAGE 15.0f // hit damage for every lerping bullet
void CGhostBusterRay_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheClass(CLASS_BULLET);
pdec->PrecacheModel(MODEL_RAY);
pdec->PrecacheTexture(TEXTURE_RAY);
}
void CGhostBusterRay::SetDefaultProperties(void) {
m_penOwner = NULL;
m_bRender = FALSE ;
m_vSrcOld = FLOAT3D(0.0f , 0.0f , 0.0f);
m_vDstOld = FLOAT3D(0.0f , 0.0f , 0.0f);
m_vSrc = FLOAT3D(0.0f , 0.0f , 0.0f);
m_vDst = FLOAT3D(0.0f , 0.0f , 0.0f);
m_iLastBulletPosition = FLOAT3D(32000.0f , 32000.0f , 32000.0f);
m_aoLightAnim.SetData(NULL);
m_ctPasses = 0;
m_penPrediction = NULL;
CMovableModelEntity::SetDefaultProperties();
}
#line 61 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::AddDependentsToPrediction(void)
#line 62 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
{
#line 63 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_penOwner -> AddToPrediction ();
#line 64 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 66 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::RenderParticles(void)
#line 67 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
{
#line 68 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
if(m_ctPasses < 2){
#line 69 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
return ;
#line 70 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 71 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
FLOAT3D vLerpedSrc = Lerp (m_vSrcOld , m_vSrc , _pTimer -> GetLerpFactor ());
#line 72 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
FLOAT3D vLerpedDst = Lerp (m_vDstOld , m_vDst , _pTimer -> GetLerpFactor ());
#line 73 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Particles_Ghostbuster (vLerpedSrc , vLerpedDst , 32 , 1.0f);
#line 74 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 77 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::Read_t(CTStream * istr)
#line 78 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
{
#line 79 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CMovableModelEntity :: Read_t (istr );
#line 80 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetupLightSource ();
#line 81 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 84 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CLightSource * CGhostBusterRay::GetLightSource(void)
#line 85 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
{
#line 86 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
if(! IsPredictor ()){
#line 87 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
return & m_lsLightSource ;
#line 88 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}else {
#line 89 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
return NULL ;
#line 90 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 91 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 94 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::SetupLightSource(void)
#line 95 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
{
#line 97 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CLightSource lsNew ;
#line 98 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ;
#line 99 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_colColor = RGBToColor (134 , 238 , 255);
#line 100 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_rFallOff = 10.0f;
#line 101 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_rHotSpot = 1.0f;
#line 102 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_plftLensFlare = NULL ;
#line 103 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_ubPolygonalMask = 0;
#line 104 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
lsNew . ls_paoLightAnimation = & m_aoLightAnim ;
#line 106 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_lsLightSource . ls_penEntity = this ;
#line 107 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_lsLightSource . SetLightSource (lsNew );
#line 108 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 115 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::DoMoving(void) {
#line 116 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
en_plLastPlacement = GetPlacement ();
#line 117 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 119 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::PostMoving(void) {
#line 120 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
if(! IsOfClass (m_penOwner , "Player Weapons")){return ;}
#line 123 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CPlacement3D plSource ;
#line 124 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CPlayerWeapons &) * m_penOwner ) . GetGhostBusterSourcePlacement (plSource );
#line 125 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
FLOAT3D vDirection , vDesired ;
#line 126 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
AnglesToDirectionVector (plSource . pl_OrientationAngle , vDirection );
#line 127 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
vDesired = vDirection * HIT_DISTANCE ;
#line 128 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
vDesired = plSource . pl_PositionVector + vDesired ;
#line 131 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CCastRay crRay (((CPlayerWeapons &) * m_penOwner ) . m_penPlayer , plSource . pl_PositionVector , vDesired );
#line 132 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_vSrcOld = m_vSrc ;
#line 133 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_vSrc = plSource . pl_PositionVector ;
#line 134 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
crRay . cr_bHitTranslucentPortals = FALSE ;
#line 135 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ;
#line 136 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
GetWorld () -> CastRay (crRay );
#line 139 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
if(crRay . cr_penHit != NULL ){
#line 140 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
vDesired = crRay . cr_vHit ;
#line 141 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 142 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
vDesired -= vDirection / 10.0f;
#line 144 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_vDstOld = m_vDst ;
#line 145 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_vDst = vDesired ;
#line 148 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
FLOAT fStretch = (plSource . pl_PositionVector - vDesired ) . Length ();
#line 150 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
GetModelObject () -> mo_Stretch (3) = 0.001f;
#line 152 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CPlacement3D plSet ;
#line 153 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
plSet . pl_PositionVector = vDesired ;
#line 154 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
plSet . pl_OrientationAngle = plSource . pl_OrientationAngle ;
#line 155 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetPlacement (plSet );
#line 156 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_ctPasses ++;
#line 157 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 165 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::PrepareBullet(const CPlacement3D & plBullet) {
#line 167 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
penBullet = CreateEntity (plBullet , CLASS_BULLET );
#line 169 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
EBulletInit eInit ;
#line 170 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
eInit . penOwner = ((CPlayerWeapons &) * m_penOwner ) . m_penPlayer ;
#line 171 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
eInit . fDamage = HIT_DAMAGE ;
#line 172 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
penBullet -> Initialize (eInit );
#line 173 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . m_EdtDamage = DMT_BULLET ;
#line 174 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 177 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::Fire(const CPlacement3D & plSource) {
#line 178 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
if(! IsOfClass (m_penOwner , "Player Weapons")){return ;}
#line 181 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
PrepareBullet (plSource );
#line 182 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . CalcTarget (HIT_DISTANCE );
#line 183 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . m_fBulletSize = 0.5f;
#line 184 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . CalcJitterTarget (0.02f * HIT_DISTANCE );
#line 185 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . LaunchBullet (TRUE , FALSE , TRUE );
#line 186 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
((CBullet &) * penBullet ) . DestroyBullet ();
#line 187 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 190 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void CGhostBusterRay::DestroyGhostBusterRay(void) {
#line 191 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Destroy ();
#line 192 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
BOOL CGhostBusterRay::
#line 201 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Main(const CEntityEvent &__eeInput) {
#undef STATE_CURRENT
#define STATE_CURRENT STATE_CGhostBusterRay_Main
ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EGhostBusterRay, "CGhostBusterRay::Main expects 'EGhostBusterRay' as input!"); const EGhostBusterRay &egbr = (const EGhostBusterRay &)__eeInput;
#line 203 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
ASSERT (egbr . penOwner != NULL );
#line 204 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_penOwner = egbr . penOwner ;
#line 207 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
InitAsModel ();
#line 208 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetPhysicsFlags (EPF_MODEL_IMMATERIAL );
#line 209 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetCollisionFlags (ECF_IMMATERIAL );
#line 210 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetModel (MODEL_RAY );
#line 211 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetModelMainTexture (TEXTURE_RAY );
#line 213 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
try {
#line 214 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_aoLightAnim . SetData_t (CTFILENAME ("Animations\\GhostbusterLightning.ani"));
#line 215 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_aoLightAnim . PlayAnim (0 , AOF_LOOPING );
#line 216 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}catch (char * strError ){
#line 217 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CPrintF ("%s" , strError );
#line 218 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
}
#line 221 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
SetupLightSource ();
#line 224 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
AddToMovers ();
#line 225 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
m_ctPasses = 0;
#line 227 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Return(STATE_CURRENT,EVoid());
#line 227 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
return TRUE; ASSERT(FALSE); return TRUE;};

View File

@ -0,0 +1,229 @@
505
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Light";
uses "Entities/Bullet";
uses "Entities/PlayerWeapons";
uses "Engine/Classes/MovableEntity";
// input parameter for ghost buster ray
event EGhostBusterRay {
CEntityPointer penOwner, // entity which owns it
};
%{
#define HIT_DISTANCE 50.0f // ray hit distance
#define HIT_DAMAGE 15.0f // hit damage for every lerping bullet
void CGhostBusterRay_OnPrecache(CDLLEntityClass *pdec, INDEX iUser)
{
pdec->PrecacheClass(CLASS_BULLET);
pdec->PrecacheModel(MODEL_RAY);
pdec->PrecacheTexture(TEXTURE_RAY);
}
%}
class CGhostBusterRay : CMovableModelEntity {
name "GhostBusterRay";
thumbnail "";
features "ImplementsOnPrecache", "CanBePredictable";
properties:
1 CEntityPointer m_penOwner, // entity which owns it
2 BOOL m_bRender = FALSE, // do not render on startup
3 FLOAT3D m_vSrcOld = FLOAT3D(0.0f, 0.0f, 0.0f),
4 FLOAT3D m_vDstOld = FLOAT3D(0.0f, 0.0f, 0.0f),
5 FLOAT3D m_vSrc = FLOAT3D(0.0f, 0.0f, 0.0f),
6 FLOAT3D m_vDst = FLOAT3D(0.0f, 0.0f, 0.0f),
10 FLOAT3D m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f), // for lerping
11 CAnimObject m_aoLightAnim,
12 INDEX m_ctPasses = 0, // for lerping initialization
{
CLightSource m_lsLightSource;
CEntity *penBullet;
const CPlacement3D *pplSource;
}
components:
1 class CLASS_LIGHT "Classes\\Light.ecl",
2 class CLASS_BULLET "Classes\\Bullet.ecl",
// ********* RAY *********
10 model MODEL_RAY "Models\\Weapons\\GhostBuster\\Projectile\\Ray.mdl",
11 texture TEXTURE_RAY "Models\\Weapons\\GhostBuster\\Projectile\\Ray.tex",
functions:
// add to prediction any entities that this entity depends on
void AddDependentsToPrediction(void)
{
m_penOwner->AddToPrediction();
}
// render particles
void RenderParticles(void)
{
if (m_ctPasses<2) {
return;
}
FLOAT3D vLerpedSrc = Lerp(m_vSrcOld, m_vSrc, _pTimer->GetLerpFactor());
FLOAT3D vLerpedDst = Lerp(m_vDstOld, m_vDst, _pTimer->GetLerpFactor());
Particles_Ghostbuster(vLerpedSrc, vLerpedDst, 32, 1.0f);
};
/* Read from stream. */
void Read_t( CTStream *istr) // throw char *
{
CMovableModelEntity::Read_t(istr);
SetupLightSource();
};
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
if (!IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
};
// Setup light source
void SetupLightSource(void)
{
// setup light source
CLightSource lsNew;
lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC;
lsNew.ls_colColor = RGBToColor(134,238,255);
lsNew.ls_rFallOff = 10.0f;
lsNew.ls_rHotSpot = 1.0f;
lsNew.ls_plftLensFlare = NULL;
lsNew.ls_ubPolygonalMask = 0;
lsNew.ls_paoLightAnimation = &m_aoLightAnim;
m_lsLightSource.ls_penEntity = this;
m_lsLightSource.SetLightSource(lsNew);
};
/************************************************************
* DO MOVING *
************************************************************/
void DoMoving(void) {
en_plLastPlacement = GetPlacement(); // remember old placement for lerping
};
void PostMoving(void) {
if (!IsOfClass(m_penOwner, "Player Weapons")) { return; }
// from current owner position move away
CPlacement3D plSource;
((CPlayerWeapons&)*m_penOwner).GetGhostBusterSourcePlacement(plSource);
FLOAT3D vDirection, vDesired;
AnglesToDirectionVector(plSource.pl_OrientationAngle, vDirection);
vDesired = vDirection*HIT_DISTANCE;
vDesired = plSource.pl_PositionVector + vDesired;
// cast a ray to find if any brush is hit
CCastRay crRay( ((CPlayerWeapons&)*m_penOwner).m_penPlayer, plSource.pl_PositionVector, vDesired);
m_vSrcOld = m_vSrc;
m_vSrc = plSource.pl_PositionVector;
crRay.cr_bHitTranslucentPortals = FALSE;
crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX;
GetWorld()->CastRay(crRay);
// if hit anything set new position
if (crRay.cr_penHit!=NULL) {
vDesired = crRay.cr_vHit;
}
vDesired -= vDirection/10.0f;
m_vDstOld = m_vDst;
m_vDst = vDesired;
// stretch model
FLOAT fStretch = (plSource.pl_PositionVector - vDesired).Length();
//GetModelObject()->mo_Stretch(3) = fStretch;
GetModelObject()->mo_Stretch(3) = 0.001f;
// set your new placement
CPlacement3D plSet;
plSet.pl_PositionVector = vDesired;
plSet.pl_OrientationAngle = plSource.pl_OrientationAngle;
SetPlacement(plSet);
m_ctPasses++;
};
/************************************************************
* FIRE FUNCTIONS *
************************************************************/
// prepare Bullet
void PrepareBullet(const CPlacement3D &plBullet) {
// create bullet
penBullet = CreateEntity(plBullet, CLASS_BULLET);
// init bullet
EBulletInit eInit;
eInit.penOwner = ((CPlayerWeapons&)*m_penOwner).m_penPlayer;
eInit.fDamage = HIT_DAMAGE;
penBullet->Initialize(eInit);
((CBullet&)*penBullet).m_EdtDamage = DMT_BULLET;
};
// fire
void Fire(const CPlacement3D &plSource) {
if (!IsOfClass(m_penOwner, "Player Weapons")) { return; }
// fire lerped bullets
PrepareBullet(plSource);
((CBullet&)*penBullet).CalcTarget(HIT_DISTANCE);
((CBullet&)*penBullet).m_fBulletSize = 0.5f;
((CBullet&)*penBullet).CalcJitterTarget(0.02f*HIT_DISTANCE);
((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE);
((CBullet&)*penBullet).DestroyBullet();
};
// destroy yourself
void DestroyGhostBusterRay(void) {
Destroy();
};
/************************************************************
* P R O C E D U R E S *
************************************************************/
procedures:
// --->>> MAIN
Main(EGhostBusterRay egbr) {
// store owner
ASSERT(egbr.penOwner!=NULL);
m_penOwner = egbr.penOwner;
// initialization
InitAsModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
SetModel(MODEL_RAY);
SetModelMainTexture(TEXTURE_RAY);
try {
m_aoLightAnim.SetData_t(CTFILENAME("Animations\\GhostbusterLightning.ani"));
m_aoLightAnim.PlayAnim(0,AOF_LOOPING);
} catch (char *strError) {
CPrintF("%s", strError);
}
// setup light source
SetupLightSource();
// add to movers list
AddToMovers();
m_ctPasses = 0;
return;
}
};

View File

@ -0,0 +1,73 @@
/*
* This file is generated by Entity Class Compiler, (c) CroTeam 1997-98
*/
#ifndef _Entities_GhostBusterRay_INCLUDED
#define _Entities_GhostBusterRay_INCLUDED 1
#include <Entities/Light.h>
#include <Entities/Bullet.h>
#include <Entities/PlayerWeapons.h>
#include <Engine/Classes/MovableEntity.h>
#define EVENTCODE_EGhostBusterRay 0x01f90000
class DECL_DLL EGhostBusterRay : public CEntityEvent {
public:
EGhostBusterRay();
CEntityEvent *MakeCopy(void);
CEntityPointer penOwner;
};
DECL_DLL inline void ClearToDefault(EGhostBusterRay &e) { e = EGhostBusterRay(); } ;
extern "C" DECL_DLL CDLLEntityClass CGhostBusterRay_DLLClass;
class CGhostBusterRay : public CMovableModelEntity {
public:
virtual CEntity *GetPredictionPair(void) { return m_penPrediction; };
virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; };
DECL_DLL virtual void SetDefaultProperties(void);
CEntityPointer m_penOwner;
BOOL m_bRender;
FLOAT3D m_vSrcOld;
FLOAT3D m_vDstOld;
FLOAT3D m_vSrc;
FLOAT3D m_vDst;
FLOAT3D m_iLastBulletPosition;
CAnimObject m_aoLightAnim;
INDEX m_ctPasses;
CEntityPointer m_penPrediction;
CLightSource m_lsLightSource;
CEntity * penBullet;
const CPlacement3D * pplSource;
#line 61 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void AddDependentsToPrediction(void);
#line 66 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void RenderParticles(void);
#line 77 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void Read_t(CTStream * istr);
#line 84 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
CLightSource * GetLightSource(void);
#line 94 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void SetupLightSource(void);
#line 115 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void DoMoving(void);
#line 119 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void PostMoving(void);
#line 165 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void PrepareBullet(const CPlacement3D & plBullet);
#line 177 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void Fire(const CPlacement3D & plSource);
#line 190 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
void DestroyGhostBusterRay(void);
#define STATE_CGhostBusterRay_Main 1
BOOL
#line 201 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Main(const CEntityEvent &__eeInput);
};
#endif // _Entities_GhostBusterRay_INCLUDED

View File

@ -0,0 +1,49 @@
/*
* This file is generated by Entity Class Compiler, (c) CroTeam 1997-98
*/
#define ENTITYCLASS CGhostBusterRay
CEntityProperty CGhostBusterRay_properties[] = {
CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f9<<8)+1, _offsetof(CGhostBusterRay, m_penOwner), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f9<<8)+2, _offsetof(CGhostBusterRay, m_bRender), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f9<<8)+3, _offsetof(CGhostBusterRay, m_vSrcOld), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f9<<8)+4, _offsetof(CGhostBusterRay, m_vDstOld), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f9<<8)+5, _offsetof(CGhostBusterRay, m_vSrc), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f9<<8)+6, _offsetof(CGhostBusterRay, m_vDst), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f9<<8)+10, _offsetof(CGhostBusterRay, m_iLastBulletPosition), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x000001f9<<8)+11, _offsetof(CGhostBusterRay, m_aoLightAnim), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001f9<<8)+12, _offsetof(CGhostBusterRay, m_ctPasses), "", 0, 0, 0),
CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f9<<8)+255, _offsetof(CGhostBusterRay, m_penPrediction), "", 0, 0, 0),
};
#define CGhostBusterRay_propertiesct ARRAYCOUNT(CGhostBusterRay_properties)
CEntityComponent CGhostBusterRay_components[] = {
#define CLASS_LIGHT ((0x000001f9<<8)+1)
CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"),
#define CLASS_BULLET ((0x000001f9<<8)+2)
CEntityComponent(ECT_CLASS, CLASS_BULLET, "EFNM" "Classes\\Bullet.ecl"),
#define MODEL_RAY ((0x000001f9<<8)+10)
CEntityComponent(ECT_MODEL, MODEL_RAY, "EFNM" "Models\\Weapons\\GhostBuster\\Projectile\\Ray.mdl"),
#define TEXTURE_RAY ((0x000001f9<<8)+11)
CEntityComponent(ECT_TEXTURE, TEXTURE_RAY, "EFNM" "Models\\Weapons\\GhostBuster\\Projectile\\Ray.tex"),
};
#define CGhostBusterRay_componentsct ARRAYCOUNT(CGhostBusterRay_components)
CEventHandlerEntry CGhostBusterRay_handlers[] = {
{1, -1, CEntity::pEventHandler(&CGhostBusterRay::
#line 201 "/home/seb/git/Serious-Seb/Sources/Entities/GhostBusterRay.es"
Main),DEBUGSTRING("CGhostBusterRay::Main")},
};
#define CGhostBusterRay_handlersct ARRAYCOUNT(CGhostBusterRay_handlers)
CEntity *CGhostBusterRay_New(void) { return new CGhostBusterRay; };
void CGhostBusterRay_OnInitClass(void) {};
void CGhostBusterRay_OnEndClass(void) {};
void CGhostBusterRay_OnPrecache(CDLLEntityClass *pdec, INDEX iUser);
void CGhostBusterRay_OnWorldEnd(CWorld *pwo) {};
void CGhostBusterRay_OnWorldInit(CWorld *pwo) {};
void CGhostBusterRay_OnWorldTick(CWorld *pwo) {};
void CGhostBusterRay_OnWorldRender(CWorld *pwo) {};
ENTITY_CLASSDEFINITION(CGhostBusterRay, CMovableModelEntity, "GhostBusterRay", "", 0x000001f9);
DECLARE_CTFILENAME(_fnmCGhostBusterRay_tbn, "");

341
Sources/Entities/Gizmo.es Normal file
View File

@ -0,0 +1,341 @@
335
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Gizmo/Gizmo.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
%{
// info structure
static EntityInfo eiGizmo = {
EIBT_FLESH, 100.0f,
0.0f, 1.3f, 0.0f, // source (eyes)
0.0f, 1.0f, 0.0f, // target (body)
};
#define EXPLODE_GIZMO 2.5f
%}
class CGizmo: CEnemyBase {
name "Gizmo";
thumbnail "Thumbnails\\Gizmo.tbn";
properties:
// class internal
1 BOOL m_bExploded = FALSE,
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl",
3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
// ************** DATA **************
10 model MODEL_GIZMO "Models\\Enemies\\Gizmo\\Gizmo.mdl",
20 texture TEXTURE_GIZMO "Models\\Enemies\\Gizmo\\Gizmo.tex",
50 sound SOUND_IDLE "Models\\Enemies\\Gizmo\\Sounds\\Idle.wav",
51 sound SOUND_JUMP "Models\\Enemies\\Gizmo\\Sounds\\Jump.wav",
52 sound SOUND_DEATH_JUMP "Models\\Enemies\\Gizmo\\Sounds\\JumpDeath.wav",
53 sound SOUND_SIGHT "Models\\Enemies\\Gizmo\\Sounds\\Sight.wav",
functions:
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
str.PrintF(TRANS("%s ate a marsh hopper"), (const char*)strPlayerName);
return str;
}
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Gizmo.txt");
return fnm;
};
/* Entity info */
void *GetEntityInfo(void)
{
return &eiGizmo;
};
void Precache(void)
{
CEnemyBase::Precache();
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_IDLE);
PrecacheSound(SOUND_JUMP);
PrecacheSound(SOUND_DEATH_JUMP);
PrecacheClass(CLASS_BASIC_EFFECT, BET_GIZMO_SPLASH_FX);
PrecacheClass(CLASS_BLOOD_SPRAY);
};
void SightSound(void) {
PlaySound(m_soSound, SOUND_SIGHT, SOF_3D);
};
void RunningAnim(void)
{
StartModelAnim(GIZMO_ANIM_RUN, 0);
};
void MortalJumpAnim(void)
{
StartModelAnim(GIZMO_ANIM_RUN, 0);
};
void StandAnim(void)
{
StartModelAnim(GIZMO_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART);
};
// virtual sound functions
void IdleSound(void) {
PlaySound(m_soSound, SOUND_IDLE, SOF_3D);
};
/************************************************************
* BLOW UP FUNCTIONS *
************************************************************/
void BlowUpNotify(void) {
Explode();
};
// explode only once
void Explode(void)
{
if (!m_bExploded)
{
m_bExploded = TRUE;
// spawn blood spray
CPlacement3D plSpray = GetPlacement();
CEntity *penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY);
penSpray->SetParent( this);
ESpawnSpray eSpawnSpray;
eSpawnSpray.fDamagePower = 2.0f;
eSpawnSpray.fSizeMultiplier = 1.0f;
eSpawnSpray.sptType = SPT_SLIME;
eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/8.0f;
eSpawnSpray.penOwner = this;
penSpray->Initialize( eSpawnSpray);
// spawn splash fx (sound)
CPlacement3D plSplash = GetPlacement();
CEntityPointer penSplash = CreateEntity(plSplash, CLASS_BASIC_EFFECT);
ESpawnEffect ese;
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_GIZMO_SPLASH_FX;
penSplash->Initialize(ese);
}
};
// gizmo should always blow up
BOOL ShouldBlowUp(void)
{
return TRUE;
}
// leave stain
virtual void LeaveStain(BOOL bGrow)
{
ESpawnEffect ese;
FLOAT3D vPoint;
FLOATplane3D vPlaneNormal;
FLOAT fDistanceToEdge;
// get your size
FLOATaabbox3D box;
GetBoundingBox(box);
// on plane
if( GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge))
{
// if near to polygon and away from last stain point
if( (vPoint-GetPlacement().pl_PositionVector).Length()<0.5f )
{
FLOAT fStretch = box.Size().Length();
// stain
ese.colMuliplier = C_WHITE|CT_OPAQUE;
ese.betType = BET_GIZMOSTAIN;
ese.vStretch = FLOAT3D( fStretch*0.75f, fStretch*0.75f, 1.0f);
ese.vNormal = FLOAT3D( vPlaneNormal);
ese.vDirection = FLOAT3D( 0, 0, 0);
FLOAT3D vPos = vPoint+ese.vNormal/50.0f*(FRnd()+0.5f);
CEntityPointer penEffect = CreateEntity( CPlacement3D(vPos, ANGLE3D(0,0,0)), CLASS_BASIC_EFFECT);
penEffect->Initialize(ese);
}
}
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
// close range -> move toward enemy and try to jump onto it
PerformAttack(EVoid) : CEnemyBase::PerformAttack
{
while (TRUE)
{
// ------------ Exit close attack if out of range or enemy is dead
// if attacking is futile
if (ShouldCeaseAttack())
{
SetTargetNone();
return EReturn();
}
// stop moving
SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f));
SetDesiredRotation(ANGLE3D(0, 0, 0));
// ------------ Wait for some time on the ground
FLOAT fWaitTime = 0.25f+FRnd()*0.4f;
wait( fWaitTime)
{
on (EBegin) : { resume; };
on (ESound) : { resume; } // ignore all sounds
on (EWatch) : { resume; } // ignore watch
on (ETimer) : { stop; } // timer tick expire
}
autocall JumpOnce() EReturn;
}
}
JumpOnce(EVoid)
{
// ------------ Jump either in slightly randomized direction or mortal, streight and fast toward enemy
// we are always going for enemy
m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector;
m_fMoveFrequency = 0.1f;
// if we are close enough for mortal jump
if( CalcPlaneDist(m_penEnemy) < 10.0f)
{
// set mortal jump parameters (no random)
m_fMoveSpeed = m_fCloseRunSpeed*1.5f;
m_aRotateSpeed = m_aCloseRotateSpeed*0.5f;
FLOAT fSpeedX = 0.0f;
FLOAT fSpeedY = 10.0f;
FLOAT fSpeedZ = -m_fMoveSpeed;
// if can't see enemy
if( !IsInFrustum(m_penEnemy, CosFast(30.0f)))
{
// rotate a lot
m_aRotateSpeed = m_aCloseRotateSpeed*1.5f;
// but don't jump too much
fSpeedY /= 2.0f;
fSpeedZ /= 4.0f;
PlaySound(m_soSound, SOUND_JUMP, SOF_3D);
}
else
{
PlaySound(m_soSound, SOUND_DEATH_JUMP, SOF_3D);
}
FLOAT3D vTranslation(fSpeedX, fSpeedY, fSpeedZ);
SetDesiredTranslation(vTranslation);
MortalJumpAnim();
}
// start slightly randomized jump
else
{
m_fMoveSpeed = m_fCloseRunSpeed;
m_aRotateSpeed = m_aCloseRotateSpeed;
// set random jump parameters
FLOAT fSpeedX = (FRnd()-0.5f)*10.0f;
FLOAT fSpeedY = FRnd()*5.0f+5.0f;
FLOAT fSpeedZ = -m_fMoveSpeed-FRnd()*2.5f;
FLOAT3D vTranslation(fSpeedX, fSpeedY, fSpeedZ);
SetDesiredTranslation(vTranslation);
RunningAnim();
PlaySound(m_soSound, SOUND_JUMP, SOF_3D);
}
// ------------ While in air, adjust directions, on touch start new jump or explode
while (TRUE)
{
// adjust direction and speed
m_fMoveSpeed = 0.0f;
m_aRotateSpeed = m_aCloseRotateSpeed;
FLOAT3D vTranslation = GetDesiredTranslation();
SetDesiredMovement();
SetDesiredTranslation(vTranslation);
wait(m_fMoveFrequency)
{
on (EBegin) : { resume; };
on (ESound) : { resume; } // ignore all sounds
on (EWatch) : { resume; } // ignore watch
on (ETimer) : { stop; } // timer tick expire
on (ETouch etouch) :
{
// if we touched ground
if( etouch.penOther->GetRenderType() & RT_BRUSH)
{
return EReturn();
}
// we touched player, explode
else if ( IsDerivedFromClass( etouch.penOther, "Player"))
{
InflictDirectDamage(etouch.penOther, this, DMT_IMPACT, 10.0f,
GetPlacement().pl_PositionVector, -en_vGravityDir);
SetHealth(-10000.0f);
m_vDamage = FLOAT3D(0,10000,0);
SendEvent(EDeath());
}
// we didn't touch ground nor player, ignore
resume;
}
}
}
};
/************************************************************
* 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);
SetHealth(9.5f);
m_fMaxHealth = 9.5f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 2000.0f;
m_fBlowUpSize = 2.0f;
// set your appearance
SetModel(MODEL_GIZMO);
SetModelMainTexture(TEXTURE_GIZMO);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd()*5.0f + 15.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
m_fCloseRunSpeed = FRnd()*5.0f + 15.0f;
m_aCloseRotateSpeed = AngleDeg(360.0f);
// setup attack distances
m_fAttackDistance = 400.0f;
m_fCloseDistance = 250.0f;
m_fStopDistance = 0.0f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 0.5f;
m_fIgnoreRange = 500.0f;
// damage/explode properties
m_fBlowUpAmount = 0.0f;
m_fBodyParts = 0;
m_fDamageWounded = 0.0f;
m_iScore = 500;
m_sptType = SPT_SLIME;
en_fDeceleration = 150.0f;
// set stretch factors for height and width
GetModelObject()->StretchModel(FLOAT3D(1.25f, 1.25f, 1.25f));
ModelChangeNotify();
StandingAnim();
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

155
Sources/Entities/Global.es Normal file
View File

@ -0,0 +1,155 @@
0
%{
#include "Entities/StdH/StdH.h"
%}
/*
*
* --->>> DON'T INSTANTIATE THIS CLASS <<<---
*
*/
event EStop { // stop your actions
};
event EStart { // start your actions
CEntityPointer penCaused, // who caused the trigger (transitive)
};
event EActivate { // activate class (usually touch field)
};
event EDeactivate { // deactivate class (usually touch field)
};
event EEnvironmentStart { // activate environment classes
};
event EEnvironmentStop { // deactivate environment classes
};
event EEnd { // general purpose end of procedure event
};
event ETrigger { // sent by trigger class
CEntityPointer penCaused, // who caused the trigger (transitive)
};
event ETeleportMovingBrush { // teleport moving brush
};
event EReminder { // reminder event
INDEX iValue, // value for return
};
event EStartAttack { // OBSOLETE!
};
event EStopAttack { // OBSOLETE!
};
event EStopBlindness { // make enemy not blind any more
};
event EStopDeafness { // make enemy not blind any more
};
event EReceiveScore { // sent to player when enemy is killed
INDEX iPoints
};
event EKilledEnemy { // sent to player when enemy is killed
};
event ESecretFound { // sent to player secret is found
};
enum BoolEType {
0 BET_TRUE "True", // true
1 BET_FALSE "False", // false
2 BET_IGNORE "Ignore", // ignore
};
enum EventEType {
0 EET_START "Start event", // start event
1 EET_STOP "Stop event", // stop event
2 EET_TRIGGER "Trigger event", // trigger event
3 EET_IGNORE "Don't send event", // don't send event (ignore)
4 EET_ACTIVATE "Activate event", // activate event
5 EET_DEACTIVATE "Deactivate event", // deactivate event
6 EET_ENVIRONMENTSTART "Start environment event", // start environment event
7 EET_ENVIRONMENTSTOP "Stop environment event", // stop environment event
8 EET_STARTATTACK "OBSOLETE! - Start attack event", // start attack enemy
9 EET_STOPATTACK "OBSOLETE! - Stop attack event", // stop attack enemy
10 EET_STOPBLINDNESS "Stop blindness event", // enemy stop being blind
11 EET_STOPDEAFNESS "Stop deafness event", // enemy stop being deaf
12 EET_TELEPORTMOVINGBRUSH "Teleport moving brush", // moving brush teleporting event
};
// entity info structure enums
enum EntityInfoBodyType {
1 EIBT_FLESH "Flesh",
2 EIBT_WATER "Water",
3 EIBT_ROCK "Rock ",
4 EIBT_FIRE "Fire ",
5 EIBT_AIR "Air ",
6 EIBT_BONES "Bones",
7 EIBT_WOOD "Wood ",
8 EIBT_METAL "Metal",
9 EIBT_ROBOT "Robot",
10 EIBT_ICE "Ice",
};
enum MessageSound {
0 MSS_NONE "None", // no sound
1 MSS_INFO "Info", // just simple info
};
enum ParticleTexture {
1 PT_STAR01 "Star01",
2 PT_STAR02 "Star02",
3 PT_STAR03 "Star03",
4 PT_STAR04 "Star04",
5 PT_STAR05 "Star05",
6 PT_STAR06 "Star06",
7 PT_STAR07 "Star07",
8 PT_STAR08 "Star08",
9 PT_BOUBBLE01 "Boubble01",
10 PT_BOUBBLE02 "Boubble02",
11 PT_WATER01 "Water01",
12 PT_WATER02 "Water02",
13 PT_SANDFLOW "Sand flow",
14 PT_WATERFLOW "Water flow",
15 PT_LAVAFLOW "Lava flow",
};
enum SoundType {
0 SNDT_NONE "", // internal
1 SNDT_SHOUT "", // enemy shout when see player
2 SNDT_YELL "", // enemy is wounded (or death)
3 SNDT_EXPLOSION "", // explosion of rocket or grenade (or similar)
4 SNDT_PLAYER "", // sound from player weapon or player is wounded
};
event ESound {
enum SoundType EsndtSound,
CEntityPointer penTarget,
};
// event for printing centered message
event ECenterMessage {
CTString strMessage, // the message
TIME tmLength, // how long to keep it
enum MessageSound mssSound, // sound to play
};
// event for sending computer message to a player
event EComputerMessage {
CTFileName fnmMessage, // the message file
};
// event for voice message to a player
event EVoiceMessage {
CTFileName fnmMessage, // the message file
};
event EHitBySpaceShipBeam {
};
class CGlobal : CEntity {
name "";
thumbnail "";
properties:
components:
functions:
procedures:
Main(EVoid) {
ASSERTALWAYS("DON'T INSTANTIATE THIS CLASS");
}
};

View File

@ -0,0 +1,93 @@
230
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
uses "Entities/WorldBase";
class CGradientMarker: CMarker {
name "Gradient Marker";
thumbnail "Thumbnails\\GradientMarker.tbn";
features "IsImportant";
properties:
1 FLOAT m_fHeight "Height" 'H' = -10.0f,
2 BOOL m_bDarkLight "Dark light" 'D' = TRUE,
3 COLOR m_colColor0 "Color 0" 'C' = (C_GRAY|CT_OPAQUE),
4 COLOR m_colColor1 "Color 1" 'A' = (C_WHITE|CT_OPAQUE),
components:
1 model MODEL_MARKER "Models\\Editor\\GradientMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\GradientMarker.tex"
functions:
/* Get gradient type name, return empty string if not used. */
const CTString &GetGradientName(void)
{
return m_strName;
}
/* Get gradient. */
BOOL GetGradient(INDEX iGradient, class CGradientParameters &gpGradient)
{
const FLOATmatrix3D &m = GetRotationMatrix();
gpGradient.gp_vGradientDir(1) = m(1,2);
gpGradient.gp_vGradientDir(2) = m(2,2);
gpGradient.gp_vGradientDir(3) = m(3,2);
FLOAT fPos = gpGradient.gp_vGradientDir%GetPlacement().pl_PositionVector;
gpGradient.gp_bDark = m_bDarkLight;
if( m_fHeight>=0 && m_fHeight<+0.001f) { m_fHeight = +0.001f; }
if( m_fHeight<=0 && m_fHeight>-0.001f) { m_fHeight = -0.001f; }
gpGradient.gp_fH0 = fPos;
gpGradient.gp_fH1 = fPos+m_fHeight;
gpGradient.gp_col0 = m_colColor0;
gpGradient.gp_col1 = m_colColor1;
return TRUE;
}
void UncacheShadowsForGradient(void)
{
// for all entities in world
FOREACHINDYNAMICCONTAINER(GetWorld()->wo_cenEntities, CEntity, iten) {
// if it is world base entity
if( IsOfClass(&*iten, "WorldBase")) {
// uncache shadows for gradient
((CWorldBase *)&*iten)->UncacheShadowsForGradient(this);
}
}
}
void SetPlacement_internal(const CPlacement3D &plNew, const FLOATmatrix3D &mRotation, BOOL bNear)
{
CEntity::SetPlacement_internal(plNew, mRotation, bNear);
UncacheShadowsForGradient();
}
void OnEnd(void)
{
UncacheShadowsForGradient();
CEntity::OnEnd();
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if( m_strName=="Marker") {
m_strName = "Gradient marker";
}
UncacheShadowsForGradient();
return;
}
};

View File

@ -0,0 +1,162 @@
212
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
uses "Entities/GravityRouter";
enum GravityType {
0 LT_PARALLEL "Parallel",
1 LT_CENTRAL "Central",
2 LT_CYLINDRICAL "Cylindirical",
3 LT_TORUS "Torus",
};
class CGravityMarker: CMarker {
name "Gravity Marker";
thumbnail "Thumbnails\\GravityMarker.tbn";
features "IsImportant";
properties:
1 enum GravityType m_gtType "Type" 'Y' =LT_PARALLEL,
2 FLOAT m_fStrength "Strength" 'S' = 1,
3 RANGE m_rFallOff "FallOff" 'F' = 50,
4 RANGE m_rHotSpot "HotSpot" 'H' = 50,
5 RANGE m_rTorusR "Torus Radius" 'R' = 100,
10 FLOAT m_fAcc = 0,
11 FLOAT m_fSign = 1,
12 FLOAT m_fStep = 0,
20 ANGLE3D m_aForceDir "Forcefield Direction" 'F' = ANGLE3D(0,0,0),
21 FLOAT m_fForceA "Forcefield Acceleration" = 0.0f,
22 FLOAT m_fForceV "Forcefield Velocity" = 0.0f,
23 FLOAT3D m_vForceDir = FLOAT3D(1,0,0),
components:
1 model MODEL_MARKER "Models\\Editor\\GravityMarker.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\GravityMarker.tex"
functions:
// find strength at given distance
inline FLOAT StrengthAtDistance(FLOAT fDistance)
{
FLOAT fStrength = (m_rFallOff-fDistance)*m_fStep;
return Clamp(fStrength, 0.0f, m_fAcc);
}
/* Get force type name, return empty string if not used. */
const CTString &GetForceName(INDEX i)
{
return m_strName;
}
/* Get force in given point. */
void GetForce(INDEX i, const FLOAT3D &vPoint,
CForceStrength &fsGravity, CForceStrength &fsField)
{
const FLOATmatrix3D &m = GetRotationMatrix();
switch (m_gtType) {
case LT_PARALLEL: {
fsGravity.fs_vDirection(1) = -m(1,2) * m_fSign;
fsGravity.fs_vDirection(2) = -m(2,2) * m_fSign;
fsGravity.fs_vDirection(3) = -m(3,2) * m_fSign;
FLOAT fDistance = (vPoint-GetPlacement().pl_PositionVector)%fsGravity.fs_vDirection;
fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance);
fsGravity.fs_fVelocity = 70;
} break;
case LT_CENTRAL: {
fsGravity.fs_vDirection = (GetPlacement().pl_PositionVector-vPoint)*m_fSign;
FLOAT fDistance = fsGravity.fs_vDirection.Length();
if (fDistance>0.01f) {
fsGravity.fs_vDirection/=fDistance;
}
fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance);
fsGravity.fs_fVelocity = 70;
} break;
case LT_CYLINDRICAL: {
FLOAT3D vDelta = GetPlacement().pl_PositionVector-vPoint;
FLOAT3D vAxis;
vAxis(1) = m(1,2);
vAxis(2) = m(2,2);
vAxis(3) = m(3,2);
GetNormalComponent(vDelta, vAxis, fsGravity.fs_vDirection);
fsGravity.fs_vDirection*=m_fSign;
FLOAT fDistance = fsGravity.fs_vDirection.Length();
if (fDistance>0.01f) {
fsGravity.fs_vDirection/=fDistance;
}
fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance);
fsGravity.fs_fVelocity = 70;
} break;
case LT_TORUS: {
// get referent point
FLOAT3D vDelta = vPoint-GetPlacement().pl_PositionVector;
FLOAT3D vAxis;
vAxis(1) = m(1,2);
vAxis(2) = m(2,2);
vAxis(3) = m(3,2);
FLOAT3D vR;
GetNormalComponent(vDelta, vAxis, vR);
vR.Normalize();
fsGravity.fs_vDirection = (vDelta-vR*m_rTorusR)*m_fSign;
FLOAT fDistance = fsGravity.fs_vDirection.Length();
if (fDistance>0.01f) {
fsGravity.fs_vDirection/=fDistance;
}
fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance);
fsGravity.fs_fVelocity = 70;
} break;
default:
fsGravity.fs_fAcceleration = m_fAcc;
fsGravity.fs_fVelocity = 70;
fsGravity.fs_vDirection = FLOAT3D(0,-1,0);
}
// calculate forcefield influence
fsField.fs_fAcceleration = m_fForceA;
fsField.fs_fVelocity = m_fForceV;
fsField.fs_vDirection = m_vForceDir;
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
if( ee.ee_slEvent==EVENTCODE_ETrigger)
{
EChangeGravity eChangeGravity;
eChangeGravity.penNewGravity = this;
m_penTarget->SendEvent( eChangeGravity);
return TRUE;
}
return FALSE;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if (m_strName=="Marker") {
m_strName = "Gravity Marker";
}
// precalc fast gravity parameters
m_fAcc = Abs(30*m_fStrength),
m_fSign = SgnNZ(m_fStrength),
m_fStep = m_fAcc/(m_rFallOff-m_rHotSpot);
AnglesToDirectionVector(m_aForceDir, m_vForceDir);
return;
}
};

View File

@ -0,0 +1,83 @@
227
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
event EChangeGravity {
CEntityPointer penNewGravity,
};
class CGravityRouter: CMarker {
name "Gravity Router";
thumbnail "Thumbnails\\GravityRouter.tbn";
features "IsImportant";
properties:
components:
1 model MODEL_MARKER "Models\\Editor\\GravityRouter.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\GravityRouter.tex"
functions:
/* Get force type name, return empty string if not used. */
const CTString &GetForceName(INDEX i)
{
return m_strName;
}
/* Get force in given point. */
void GetForce(INDEX i, const FLOAT3D &vPoint,
CForceStrength &fsGravity, CForceStrength &fsField)
{
if( (m_penTarget != NULL) && (IsOfClass( m_penTarget, "Gravity Marker")))
{
m_penTarget->GetForce(i, vPoint, fsGravity, fsField);
}
}
/* Get entity that controls the force, used for change notification checking. */
CEntity *GetForceController(INDEX iForce)
{
return this;
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
if( ((EChangeGravity &) ee).ee_slEvent==EVENTCODE_EChangeGravity)
{
m_penTarget = ((EChangeGravity &) ee).penNewGravity;
// notify engine that gravity defined by this entity has changed
NotifyGravityChanged();
return TRUE;
}
return FALSE;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if (m_strName=="Marker") {
m_strName = "Gravity Router";
}
if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Gravity Marker")) {
WarningMessage( "Entity '%s' is not of Gravity Marker class!", (const char*)m_penTarget->GetName());
m_penTarget = NULL;
}
return;
}
};

View File

@ -0,0 +1,126 @@
216
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/Marker";
uses "Entities/FogMarker";
class CHazeMarker: CMarker {
name "Haze Marker";
thumbnail "Thumbnails\\HazeMarker.tbn";
features "IsImportant";
properties:
10 enum FogAttenuationType m_faType "Attenuation Type" 'A' =FA_EXP,
11 FLOAT m_fDensity "Density" 'D' = 0.1f,
12 FLOAT m_fNear "Near" = 100.0f,
13 FLOAT m_fFar "Far" = 1000.0f,
14 BOOL m_bVisibleFromOutside "Visible from outside" = FALSE,
22 INDEX m_iSize "Size" = 32,
23 COLOR m_colBase "Base Color" 'C' = (C_WHITE|CT_OPAQUE),
24 COLOR m_colUp "Color (up)" = (C_BLACK|CT_TRANSPARENT),
25 COLOR m_colDown "Color (down)" = (C_BLACK|CT_TRANSPARENT),
26 COLOR m_colNorth "Color (north)" = (C_BLACK|CT_TRANSPARENT),
27 COLOR m_colSouth "Color (south)" = (C_BLACK|CT_TRANSPARENT),
28 COLOR m_colEast "Color (east)" = (C_BLACK|CT_TRANSPARENT),
29 COLOR m_colWest "Color (west)" = (C_BLACK|CT_TRANSPARENT),
components:
1 model MODEL_MARKER "Models\\Editor\\Haze.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Haze.tex"
functions:
/* Get haze type name, return empty string if not used. */
const CTString &GetHazeName(void)
{
return m_strName;
}
/* Get haze. */
void GetHaze(class CHazeParameters &hpHaze, FLOAT3D &vViewDir)
{
// calculate directional haze color
COLOR colDir=C_BLACK, colMul;
FLOAT fR=0.0f, fG=0.0f, fB=0.0f, fA=0.0f;
FLOAT fSum = 255.0f / (Abs(vViewDir(1))+Abs(vViewDir(2))+Abs(vViewDir(3)));
if( vViewDir(1) < 0.0f) {
colMul = (COLOR)(-vViewDir(1)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colWest, colMul));
}
if( vViewDir(1) > 0.0f) {
colMul = (COLOR)(+vViewDir(1)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colEast, colMul));
}
if( vViewDir(2) < 0.0f) {
colMul = (COLOR)(-vViewDir(2)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colDown, colMul));
}
if( vViewDir(2) > 0.0f) {
colMul = (COLOR)(+vViewDir(2)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colUp, colMul));
}
if( vViewDir(3) < 0.0f) {
colMul = (COLOR)(-vViewDir(3)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colNorth, colMul));
}
if( vViewDir(3) > 0.0f) {
colMul = (COLOR)(+vViewDir(3)*fSum);
colMul = (colMul<<CT_RSHIFT) | (colMul<<CT_GSHIFT) | (colMul<<CT_BSHIFT) | (colMul<<CT_ASHIFT);
colDir = AddColors( colDir, MulColors( m_colSouth, colMul));
}
// blend base and direction haze color
colDir = AddColors( colDir, m_colBase);
// assign parameters
hpHaze.hp_colColor = colDir;
hpHaze.hp_atType = (AttenuationType) m_faType;
hpHaze.hp_fDensity = m_fDensity;
hpHaze.hp_fNear = m_fNear;
hpHaze.hp_fFar = m_fFar;
hpHaze.hp_iSize = m_iSize;
hpHaze.hp_ulFlags = 0;
if (m_bVisibleFromOutside) {
hpHaze.hp_ulFlags |= HPF_VISIBLEFROMOUTSIDE;
}
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
// set name
if (m_strName=="Marker") {
m_strName = "Haze marker";
}
// clamp values to valid ranges
m_fDensity = ClampDn(m_fDensity, 1E-6f);
m_fFar = ClampDn(m_fFar, 0.001f);
m_fNear = Clamp(m_fNear, 0.0f, m_fFar-0.0005f);
ASSERT(m_fNear>=0 && m_fNear<m_fFar);
m_iSize = 1<<INDEX(Log2(m_iSize));
m_iSize= Clamp(m_iSize, INDEX(2), INDEX(256));
return;
}
};

691
Sources/Entities/Headman.es Normal file
View File

@ -0,0 +1,691 @@
303
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Headman/headman.h"
%}
uses "Entities/EnemyBase";
uses "Entities/BasicEffects";
enum HeadmanType {
0 HDT_FIRECRACKER "Fire Cracker",
1 HDT_ROCKETMAN "Rocketman",
2 HDT_BOMBERMAN "Bomberman",
3 HDT_KAMIKAZE "Kamikaze",
};
%{
// info structure
static EntityInfo eiHeadman = {
EIBT_FLESH, 100.0f,
0.0f, 1.9f, 0.0f, // source (eyes)
0.0f, 1.0f, 0.0f, // target (body)
};
#define EXPLODE_KAMIKAZE 2.5f
#define BOMBERMAN_ANGLE (45.0f)
#define BOMBERMAN_LAUNCH (FLOAT3D(0.0f, 1.5f, 0.0f))
%}
class CHeadman: CEnemyBase {
name "Headman";
thumbnail "Thumbnails\\Headman.tbn";
properties:
1 enum HeadmanType m_hdtType "Type" 'Y' = HDT_FIRECRACKER,
// class internal
5 BOOL m_bExploded = FALSE,
6 BOOL m_bAttackSound = FALSE, // playing kamikaze yelling sound
components:
1 class CLASS_BASE "Classes\\EnemyBase.ecl",
2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl",
3 class CLASS_PROJECTILE "Classes\\Projectile.ecl",
10 model MODEL_HEADMAN "Models\\Enemies\\Headman\\Headman.mdl",
11 model MODEL_HEAD "Models\\Enemies\\Headman\\Head.mdl",
12 model MODEL_FIRECRACKERHEAD "Models\\Enemies\\Headman\\FirecrackerHead.mdl",
13 model MODEL_CHAINSAW "Models\\Enemies\\Headman\\ChainSaw.mdl",
15 model MODEL_ROCKETLAUNCHER "Models\\Enemies\\Headman\\RocketLauncher.mdl",
17 model MODEL_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl",
20 texture TEXTURE_BOMBERMAN "Models\\Enemies\\Headman\\Bomberman.tex",
21 texture TEXTURE_FIRECRACKER "Models\\Enemies\\Headman\\Firecracker.tex",
22 texture TEXTURE_KAMIKAZE "Models\\Enemies\\Headman\\Kamikaze.tex",
23 texture TEXTURE_ROCKETMAN "Models\\Enemies\\Headman\\Rocketman.tex",
24 texture TEXTURE_HEAD "Models\\Enemies\\Headman\\Head.tex",
25 texture TEXTURE_FIRECRACKERHEAD "Models\\Enemies\\Headman\\FirecrackerHead.tex",
26 texture TEXTURE_CHAINSAW "Models\\Enemies\\Headman\\Chainsaw.tex",
28 texture TEXTURE_ROCKETLAUNCHER "Models\\Enemies\\Headman\\RocketLauncher.tex",
29 texture TEXTURE_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Headman\\Sounds\\Idle.wav",
51 sound SOUND_IDLEKAMIKAZE "Models\\Enemies\\Headman\\Sounds\\IdleKamikaze.wav",
52 sound SOUND_SIGHT "Models\\Enemies\\Headman\\Sounds\\Sight.wav",
53 sound SOUND_WOUND "Models\\Enemies\\Headman\\Sounds\\Wound.wav",
54 sound SOUND_FIREROCKETMAN "Models\\Enemies\\Headman\\Sounds\\FireRocketman.wav",
55 sound SOUND_FIREFIRECRACKER "Models\\Enemies\\Headman\\Sounds\\FireFirecracker.wav",
56 sound SOUND_FIREBOMBERMAN "Models\\Enemies\\Headman\\Sounds\\FireBomberman.wav",
57 sound SOUND_ATTACKKAMIKAZE "Models\\Enemies\\Headman\\Sounds\\AttackKamikaze.wav",
58 sound SOUND_DEATH "Models\\Enemies\\Headman\\Sounds\\Death.wav",
/*
60 model MODEL_HEADMAN_BODY "Models\\Enemies\\Headman\\Debris\\Torso.mdl",
61 model MODEL_HEADMAN_HAND "Models\\Enemies\\Headman\\Debris\\Arm.mdl",
62 model MODEL_HEADMAN_LEGS "Models\\Enemies\\Headman\\Debris\\Leg.mdl",
*/
functions:
// describe how this enemy killed player
virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath)
{
CTString str;
if (eDeath.eLastDamage.dmtType==DMT_EXPLOSION) {
if (m_hdtType==HDT_BOMBERMAN) {
str.PrintF(TRANS("%s was bombed by a Bomberman"),(const char*) strPlayerName);
} else {
str.PrintF(TRANS("%s fell victim of a Kamikaze"),(const char*) strPlayerName);
}
} else if (m_hdtType==HDT_ROCKETMAN) {
str.PrintF(TRANS("A Rocketeer tickled %s to death"),(const char*) strPlayerName);
} else if (m_hdtType==HDT_FIRECRACKER) {
str.PrintF(TRANS("A Firecracker tickled %s to death"),(const char*) strPlayerName);
}
return str;
}
/* Entity info */
void *GetEntityInfo(void) {
return &eiHeadman;
};
virtual const CTFileName &GetComputerMessageName(void) const {
static DECLARE_CTFILENAME(fnmRocketman, "Data\\Messages\\Enemies\\Rocketman.txt");
static DECLARE_CTFILENAME(fnmFirecracker, "Data\\Messages\\Enemies\\Firecracker.txt");
static DECLARE_CTFILENAME(fnmBomberman, "Data\\Messages\\Enemies\\Bomberman.txt");
static DECLARE_CTFILENAME(fnmKamikaze, "Data\\Messages\\Enemies\\Kamikaze.txt");
switch(m_hdtType) {
default: ASSERT(FALSE);
case HDT_ROCKETMAN: return fnmRocketman;
case HDT_FIRECRACKER: return fnmFirecracker;
case HDT_BOMBERMAN: return fnmBomberman;
case HDT_KAMIKAZE: return fnmKamikaze;
}
};
void Precache(void) {
CEnemyBase::Precache();
PrecacheSound(SOUND_IDLE);
PrecacheSound(SOUND_SIGHT);
PrecacheSound(SOUND_WOUND);
PrecacheSound(SOUND_DEATH);
switch(m_hdtType) {
case HDT_FIRECRACKER: {
PrecacheSound(SOUND_FIREFIRECRACKER);
PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_FIRECRACKER);
} break;
case HDT_ROCKETMAN: {
PrecacheSound(SOUND_FIREROCKETMAN);
PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_ROCKETMAN);
} break;
case HDT_BOMBERMAN: {
PrecacheSound(SOUND_FIREBOMBERMAN);
PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_BOMBERMAN);
PrecacheModel(MODEL_BOMB);
PrecacheTexture(TEXTURE_BOMB);
} break;
case HDT_KAMIKAZE: {
PrecacheSound(SOUND_ATTACKKAMIKAZE);
PrecacheSound(SOUND_IDLEKAMIKAZE);
PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB);
PrecacheModel(MODEL_BOMB);
PrecacheTexture(TEXTURE_BOMB);
} break;
}
};
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
CEnemyBase::FillEntityStatistics(pes);
switch(m_hdtType) {
case HDT_FIRECRACKER: { pes->es_strName+=" Firecracker"; } break;
case HDT_ROCKETMAN: { pes->es_strName+=" Rocketman"; } break;
case HDT_BOMBERMAN: { pes->es_strName+=" Bomberman"; } break;
case HDT_KAMIKAZE: { pes->es_strName+=" Kamikaze"; } break;
}
return TRUE;
}
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// firecracker and rocketman can't harm headman
if (!IsOfClass(penInflictor, "Headman") ||
!(((CHeadman*)penInflictor)->m_hdtType==HDT_FIRECRACKER ||
((CHeadman*)penInflictor)->m_hdtType==HDT_ROCKETMAN)) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
if (IRnd()%2) {
iAnim = HEADMAN_ANIM_WOUND1;
} else {
iAnim = HEADMAN_ANIM_WOUND2;
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
FLOAT3D vFront;
GetHeadingDirection(0, vFront);
FLOAT fDamageDir = m_vDamage%vFront;
if (fDamageDir<0) {
if (Abs(fDamageDir)<10.0f) {
iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_BACK;
} else {
iAnim = HEADMAN_ANIM_DEATH_FALL_BACK;
}
} else {
if (Abs(fDamageDir)<10.0f) {
iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_FORWARD;
} else {
iAnim = HEADMAN_ANIM_DEATH_FALL_ON_KNEES;
}
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// should this enemy blow up (spawn debris)
BOOL ShouldBlowUp(void)
{
if (m_hdtType==HDT_KAMIKAZE && GetHealth()<=0) {
return TRUE;
} else {
return CEnemyBase::ShouldBlowUp();
}
}
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(HEADMAN_ANIM_IDLE_PATROL, AOF_LOOPING|AOF_NORESTART);
if (m_hdtType==HDT_KAMIKAZE) {
KamikazeSoundOff();
}
};
void StandingAnimFight(void)
{
StartModelAnim(HEADMAN_ANIM_IDLE_FIGHT, AOF_LOOPING|AOF_NORESTART);
if (m_hdtType==HDT_KAMIKAZE) {
KamikazeSoundOff();
}
}
void WalkingAnim(void) {
StartModelAnim(HEADMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void) {
if (m_hdtType==HDT_KAMIKAZE) {
KamikazeSoundOn();
StartModelAnim(HEADMAN_ANIM_KAMIKAZE_ATTACK, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(HEADMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
}
};
void RotatingAnim(void) {
RunningAnim();
};
// virtual sound functions
void IdleSound(void) {
if (m_bAttackSound) {
return;
}
if (m_hdtType==HDT_KAMIKAZE) {
PlaySound(m_soSound, SOUND_IDLEKAMIKAZE, SOF_3D);
} else {
PlaySound(m_soSound, SOUND_IDLE, SOF_3D);
}
};
void SightSound(void) {
if (m_bAttackSound) {
return;
}
PlaySound(m_soSound, SOUND_SIGHT, SOF_3D);
};
void WoundSound(void) {
if (m_bAttackSound) {
return;
}
PlaySound(m_soSound, SOUND_WOUND, SOF_3D);
};
void DeathSound(void) {
if (m_bAttackSound) {
return;
}
PlaySound(m_soSound, SOUND_DEATH, SOF_3D);
};
void KamikazeSoundOn(void) {
if (!m_bAttackSound) {
m_bAttackSound = TRUE;
PlaySound(m_soSound, SOUND_ATTACKKAMIKAZE, SOF_3D|SOF_LOOP);
}
}
void KamikazeSoundOff(void) {
if (m_bAttackSound) {
m_soSound.Stop();
m_bAttackSound = FALSE;
}
}
/************************************************************
* BLOW UP FUNCTIONS *
************************************************************/
void BlowUpNotify(void) {
// kamikaze and bomberman explode if is not already exploded
if (m_hdtType==HDT_KAMIKAZE || m_hdtType==HDT_BOMBERMAN) {
Explode();
}
};
// spawn body parts
/*void BlowUp(void)
{
if( m_hdtType==HDT_FIRECRACKER || m_hdtType==HDT_ROCKETMAN)
{
// get your size
FLOATaabbox3D box;
GetBoundingBox(box);
FLOAT fEntitySize = box.Size().MaxNorm();
FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length());
vNormalizedDamage /= Sqrt(vNormalizedDamage.Length());
vNormalizedDamage *= 0.75f;
FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute);
// spawn debris
Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fEntitySize, vNormalizedDamage, vBodySpeed, 5.0f, 2.0f);
INDEX iTextureID = TEXTURE_ROCKETMAN;
if( m_hdtType==HDT_FIRECRACKER)
{
iTextureID = TEXTURE_FIRECRACKER;
}
Debris_Spawn(this, this, MODEL_HEADMAN_BODY, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_HEADMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_HEADMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
Debris_Spawn(this, this, MODEL_HEADMAN_LEGS, iTextureID, 0, 0, 0, 0, 0.0f,
FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f));
// hide yourself (must do this after spawning debris)
SwitchToEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
}
else
{
CEnemyBase::BlowUp();
}
};*/
// bomberman and kamikaze explode only once
void Explode(void) {
if (!m_bExploded) {
m_bExploded = TRUE;
// inflict damage
FLOAT3D vSource;
GetEntityInfoPosition(this, eiHeadman.vTargetCenter, vSource);
if (m_hdtType==HDT_BOMBERMAN) {
InflictDirectDamage(this, this, DMT_EXPLOSION, 100.0f, vSource,
-en_vGravityDir);
InflictRangeDamage(this, DMT_EXPLOSION, 15.0f, vSource, 1.0f, 6.0f);
} else {
InflictDirectDamage(this, this, DMT_CLOSERANGE, 100.0f, vSource,
-en_vGravityDir);
InflictRangeDamage(this, DMT_EXPLOSION, 30.0f, vSource, 2.75f, 8.0f);
}
// spawn explosion
CPlacement3D plExplosion = GetPlacement();
CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT);
ESpawnEffect eSpawnEffect;
eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE;
eSpawnEffect.betType = BET_BOMB;
eSpawnEffect.vStretch = FLOAT3D(1.0f,1.0f,1.0f);
penExplosion->Initialize(eSpawnEffect);
}
};
// ******
// overrides from CEnemyBase to provide exploding on close range
// set speeds for movement towards desired position
void SetSpeedsToDesiredPosition(const FLOAT3D &vPosDelta, FLOAT fPosDistance, BOOL bGoingToPlayer)
{
// if very close to player
if (m_hdtType==HDT_KAMIKAZE && CalcDist(m_penEnemy) < EXPLODE_KAMIKAZE) {
// explode
SetHealth(-10000.0f);
m_vDamage = FLOAT3D(0,10000,0);
SendEvent(EDeath());
// if not close
} else {
// behave as usual
CEnemyBase::SetSpeedsToDesiredPosition(vPosDelta, fPosDistance, bGoingToPlayer);
}
}
// get movement frequency for attack
virtual FLOAT GetAttackMoveFrequency(FLOAT fEnemyDistance)
{
// kamikaze must have sharp reflexes when close
if (m_hdtType==HDT_KAMIKAZE && fEnemyDistance < m_fCloseDistance) {
return 0.1f;
} else {
return CEnemyBase::GetAttackMoveFrequency(fEnemyDistance);
}
}
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
InitializeAttack(EVoid) : CEnemyBase::InitializeAttack {
if (m_hdtType==HDT_KAMIKAZE) {
KamikazeSoundOn();
}
jump CEnemyBase::InitializeAttack();
};
StopAttack(EVoid) : CEnemyBase::StopAttack {
KamikazeSoundOff();
jump CEnemyBase::StopAttack();
};
Fire(EVoid) : CEnemyBase::Fire {
// firecracker
if (m_hdtType == HDT_FIRECRACKER) {
autocall FirecrackerAttack() EEnd;
// rocketman
} else if (m_hdtType == HDT_ROCKETMAN) {
autocall RocketmanAttack() EEnd;
// bomber
} else if (m_hdtType == HDT_BOMBERMAN) {
autocall BombermanAttack() EEnd;
// kamikaze
} else if (m_hdtType == HDT_KAMIKAZE) {
}
return EReturn();
};
// Bomberman attack
BombermanAttack(EVoid) {
// don't shoot if enemy above or below you too much
if ( !IsInFrustum(m_penEnemy, CosFast(80.0f)) ) {
return EEnd();
}
autowait(0.2f + FRnd()/4);
StartModelAnim(HEADMAN_ANIM_BOMBERMAN_ATTACK, 0);
PlaySound(m_soSound, SOUND_FIREBOMBERMAN, SOF_3D);
autowait(0.15f);
AddAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, MODEL_BOMB, TEXTURE_BOMB);
autowait(0.30f);
RemoveAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND);
// hit bomb
// calculate launch velocity and heading correction for angular launch
FLOAT fLaunchSpeed;
FLOAT fRelativeHdg;
CalculateAngularLaunchParams(
GetPlacement().pl_PositionVector, BOMBERMAN_LAUNCH(2)-1.5f,
m_penEnemy->GetPlacement().pl_PositionVector, FLOAT3D(0,0,0),
BOMBERMAN_ANGLE,
fLaunchSpeed,
fRelativeHdg);
// target enemy body
EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo());
FLOAT3D vShootTarget;
GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget);
// launch
CPlacement3D pl;
PrepareFreeFlyingProjectile(pl, vShootTarget, BOMBERMAN_LAUNCH, ANGLE3D(0, BOMBERMAN_ANGLE, 0));
CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE);
ELaunchProjectile eLaunch;
eLaunch.penLauncher = this;
eLaunch.prtType = PRT_HEADMAN_BOMBERMAN;
eLaunch.fSpeed = fLaunchSpeed;
penProjectile->Initialize(eLaunch);
// safety remove - if hitted (EWounded) while have bomb in his hand, bomb will never be removed
RemoveAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND);
autowait(0.45f + FRnd()/2);
return EEnd();
};
// Firecraker attack
FirecrackerAttack(EVoid) {
// don't shoot if enemy above you more than quare of two far from you
if (-en_vGravityDir%CalcDelta(m_penEnemy) > CalcDist(m_penEnemy)/1.41421f) {
return EEnd();
}
autowait(0.2f + FRnd()/4);
StartModelAnim(HEADMAN_ANIM_FIRECRACKER_ATTACK, 0);
autowait(0.15f);
PlaySound(m_soSound, SOUND_FIREFIRECRACKER, SOF_3D);
autowait(0.52f);
ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(-16.0f, 0, 0));
autowait(0.05f);
ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(-8, 0, 0));
autowait(0.05f);
ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(0.0f, 0, 0));
autowait(0.05f);
ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(8.0f, 0, 0));
autowait(0.05f);
ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(16.0f, 0, 0));
autowait(0.5f + FRnd()/3);
return EEnd();
};
// Rocketman attack
RocketmanAttack(EVoid) {
StandingAnimFight(); //StartModelAnim(_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
autowait(0.2f + FRnd()/4);
StartModelAnim(HEADMAN_ANIM_ROCKETMAN_ATTACK, 0);
ShootProjectile(PRT_HEADMAN_ROCKETMAN, FLOAT3D(0.0f, 1.0f, 0.0f), ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIREROCKETMAN, SOF_3D);
autowait(1.0f + FRnd()/3);
return EEnd();
};
/************************************************************
* D E A T H *
************************************************************/
Death(EVoid) : CEnemyBase::Death {
ASSERT(m_hdtType!=HDT_KAMIKAZE);
// death
autocall CEnemyBase::Death() EEnd;
// bomberman explode
if (m_hdtType==HDT_BOMBERMAN) {
Explode();
}
return EEnd();
};
/************************************************************
* 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);
SetHealth(19.5f);
m_fMaxHealth = 19.5f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 2000.0f;
m_fBlowUpSize = 2.0f;
// set your appearance
SetModel(MODEL_HEADMAN);
switch (m_hdtType) {
case HDT_FIRECRACKER:
// set your texture
SetModelMainTexture(TEXTURE_FIRECRACKER);
AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_FIRECRACKERHEAD, TEXTURE_FIRECRACKERHEAD);
AddAttachment(HEADMAN_ATTACHMENT_CHAINSAW, MODEL_CHAINSAW, TEXTURE_CHAINSAW);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd() + 5.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd() + 5.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 8.0f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 65.0f;
m_fBodyParts = 4;
m_fDamageWounded = 0.0f;
m_iScore = 200;
break;
case HDT_ROCKETMAN:
// set your texture
SetModelMainTexture(TEXTURE_ROCKETMAN);
AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_HEAD, TEXTURE_HEAD);
AddAttachment(HEADMAN_ATTACHMENT_ROCKET_LAUNCHER, MODEL_ROCKETLAUNCHER, TEXTURE_ROCKETLAUNCHER);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd()*2.0f + 6.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 6.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 8.0f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 65.0f;
m_fBodyParts = 4;
m_fDamageWounded = 0.0f;
m_iScore = 100;
break;
case HDT_BOMBERMAN:
// set your texture
SetModelMainTexture(TEXTURE_BOMBERMAN);
AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_HEAD, TEXTURE_HEAD);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd() + 4.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd() + 4.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 45.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 20.0f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 1.5f;
m_fIgnoreRange = 150.0f;
// damage/explode properties
m_fBlowUpAmount = 65.0f;
m_fBodyParts = 4;
m_fDamageWounded = 0.0f;
m_iScore = 500;
break;
case HDT_KAMIKAZE:
// set your texture
SetModelMainTexture(TEXTURE_KAMIKAZE);
AddAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, MODEL_BOMB, TEXTURE_BOMB);
AddAttachment(HEADMAN_ATTACHMENT_BOMB_LEFT_HAND, MODEL_BOMB, TEXTURE_BOMB);
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f);
m_fAttackRunSpeed = FRnd()*2.0f + 10.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 10.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 10.0f;
m_fStopDistance = 0.0f;
m_fAttackFireTime = 2.0f;
m_fCloseFireTime = 0.5f;
m_fIgnoreRange = 250.0f;
// damage/explode properties
m_fBlowUpAmount = 0.0f;
m_fBodyParts = 4;
m_fDamageWounded = 0.0f;
m_iScore = 2500;
break;
}
// set stretch factors for height and width
GetModelObject()->StretchModel(FLOAT3D(1.25f, 1.25f, 1.25f));
ModelChangeNotify();
StandingAnim();
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,263 @@
801
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
uses "Entities/Item";
// health type
enum HealthItemType {
0 HIT_PILL "Pill", // pill health
1 HIT_SMALL "Small", // small health
2 HIT_MEDIUM "Medium", // medium health
3 HIT_LARGE "Large", // large health
4 HIT_SUPER "Super", // super health
};
// event for sending through receive item
event EHealth {
FLOAT fHealth, // health to receive
BOOL bOverTopHealth, // can be received over top health
};
class CHealthItem : CItem {
name "Health Item";
thumbnail "Thumbnails\\HealthItem.tbn";
properties:
1 enum HealthItemType m_EhitType "Type" 'Y' = HIT_SMALL, // health type
2 BOOL m_bOverTopHealth = FALSE, // can be received over top health
3 INDEX m_iSoundComponent = 0,
components:
0 class CLASS_BASE "Classes\\Item.ecl",
// ********* PILL HEALTH *********
1 model MODEL_PILL "Models\\Items\\Health\\Pill\\Pill.mdl",
2 texture TEXTURE_PILL "Models\\Items\\Health\\Pill\\Pill.tex",
3 texture TEXTURE_PILL_BUMP "Models\\Items\\Health\\Pill\\PillBump.tex",
// ********* SMALL HEALTH *********
10 model MODEL_SMALL "Models\\Items\\Health\\Small\\Small.mdl",
11 texture TEXTURE_SMALL "Models\\Items\\Health\\Small\\Small.tex",
// ********* MEDIUM HEALTH *********
20 model MODEL_MEDIUM "Models\\Items\\Health\\Medium\\Medium.mdl",
21 texture TEXTURE_MEDIUM "Models\\Items\\Health\\Medium\\Medium.tex",
// ********* LARGE HEALTH *********
30 model MODEL_LARGE "Models\\Items\\Health\\Large\\Large.mdl",
31 texture TEXTURE_LARGE "Models\\Items\\Health\\Large\\Large.tex",
// ********* SUPER HEALTH *********
40 model MODEL_SUPER "Models\\Items\\Health\\Super\\Super.mdl",
41 texture TEXTURE_SUPER "Models\\Items\\Health\\Super\\Super.tex",
// ********* MISC *********
50 texture TEXTURE_SPECULAR_STRONG "Models\\SpecularTextures\\Strong.tex",
51 texture TEXTURE_SPECULAR_MEDIUM "Models\\SpecularTextures\\Medium.tex",
52 texture TEXTURE_REFLECTION_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
53 texture TEXTURE_REFLECTION_GOLD01 "Models\\ReflectionTextures\\Gold01.tex",
54 texture TEXTURE_REFLECTION_PUPLE01 "Models\\ReflectionTextures\\Purple01.tex",
55 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
56 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
// ************** SOUNDS **************
301 sound SOUND_PILL "Sounds\\Items\\HealthPill.wav",
302 sound SOUND_SMALL "Sounds\\Items\\HealthSmall.wav",
303 sound SOUND_MEDIUM "Sounds\\Items\\HealthMedium.wav",
304 sound SOUND_LARGE "Sounds\\Items\\HealthLarge.wav",
305 sound SOUND_SUPER "Sounds\\Items\\HealthSuper.wav",
functions:
void Precache(void) {
switch (m_EhitType) {
case HIT_PILL: PrecacheSound(SOUND_PILL ); break;
case HIT_SMALL: PrecacheSound(SOUND_SMALL ); break;
case HIT_MEDIUM: PrecacheSound(SOUND_MEDIUM); break;
case HIT_LARGE: PrecacheSound(SOUND_LARGE ); break;
case HIT_SUPER: PrecacheSound(SOUND_SUPER ); break;
}
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_strName = "Health";
pes->es_ctCount = 1;
pes->es_ctAmmount = m_fValue;
pes->es_fValue = m_fValue;
pes->es_iScore = 0;//m_iScore;
switch (m_EhitType) {
case HIT_PILL: pes->es_strName+=" pill"; break;
case HIT_SMALL: pes->es_strName+=" small"; break;
case HIT_MEDIUM:pes->es_strName+=" medium"; break;
case HIT_LARGE: pes->es_strName+=" large"; break;
case HIT_SUPER: pes->es_strName+=" super"; break;
}
return TRUE;
}
// render particles
void RenderParticles(void) {
// no particles when not existing or in DM modes
if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE
|| !ShowItemParticles())
{
return;
}
switch (m_EhitType) {
case HIT_PILL:
Particles_Stardust(this, 0.9f*0.75f, 0.70f*0.75f, PT_STAR08, 32);
break;
case HIT_SMALL:
Particles_Stardust(this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128);
break;
case HIT_MEDIUM:
Particles_Stardust(this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128);
break;
case HIT_LARGE:
Particles_Stardust(this, 2.0f*0.75f, 1.0f*0.75f, PT_STAR08, 192);
break;
case HIT_SUPER:
Particles_Stardust(this, 2.3f*0.75f, 1.5f*0.75f, PT_STAR08, 320);
break;
}
}
// set health properties depending on health type
void SetProperties(void) {
switch (m_EhitType) {
case HIT_PILL:
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL);
m_fValue = 1.0f;
m_bOverTopHealth = TRUE;
m_fRespawnTime = 10.0f;
m_strDescription.PrintF("Pill - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_PILL, TEXTURE_PILL, 0, TEXTURE_SPECULAR_STRONG, TEXTURE_PILL_BUMP);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75));
m_iSoundComponent = SOUND_PILL;
break;
case HIT_SMALL:
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 10.0f;
m_bOverTopHealth = FALSE;
m_fRespawnTime = 10.0f;
m_strDescription.PrintF("Small - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_SMALL, TEXTURE_SMALL, TEXTURE_REFLECTION_LIGHTMETAL01, TEXTURE_SPECULAR_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.4f,0), FLOAT3D(2,2,0.4f) );
StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75));
m_iSoundComponent = SOUND_SMALL;
break; // add flare
case HIT_MEDIUM:
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 25.0f;
m_bOverTopHealth = FALSE;
m_fRespawnTime = 25.0f;
m_strDescription.PrintF("Medium - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_MEDIUM, TEXTURE_MEDIUM, TEXTURE_REFLECTION_LIGHTMETAL01, TEXTURE_SPECULAR_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2.5f,2.5f,0.5f) );
StretchItem(FLOAT3D(1.5f*0.75f, 1.5f*0.75f, 1.5f*0.75));
m_iSoundComponent = SOUND_MEDIUM;
break;
case HIT_LARGE:
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 50.0f;
m_bOverTopHealth = FALSE;
m_fRespawnTime = 60.0f;
m_strDescription.PrintF("Large - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_LARGE, TEXTURE_LARGE, TEXTURE_REFLECTION_GOLD01, TEXTURE_SPECULAR_STRONG, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.8f,0), FLOAT3D(2.8f,2.8f,1.0f) );
StretchItem(FLOAT3D(1.2f*0.75f, 1.2f*0.75f, 1.2f*0.75));
m_iSoundComponent = SOUND_LARGE;
break;
case HIT_SUPER:
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM);
m_fValue = 100.0f;
m_bOverTopHealth = TRUE;
m_fRespawnTime = 120.0f;
m_strDescription.PrintF("Super - H:%g T:%g", m_fValue, m_fRespawnTime);
// set appearance
AddItem(MODEL_SUPER, TEXTURE_SUPER, 0, TEXTURE_SPECULAR_MEDIUM, 0);
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,1.0f,0), FLOAT3D(3,3,1.0f) );
StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75));
CModelObject &mo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject;
mo.PlayAnim(0, AOF_LOOPING);
m_iSoundComponent = SOUND_SUPER;
break;
}
};
void AdjustDifficulty(void)
{
if (!GetSP()->sp_bAllowHealth && m_penTarget==NULL) {
Destroy();
}
}
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected {
ASSERT(epass.penOther!=NULL);
// if health stays
if (GetSP()->sp_bHealthArmorStays && !m_bPickupOnce) {
// if already picked by this player
BOOL bWasPicked = MarkPickedBy(epass.penOther);
if (bWasPicked) {
// don't pick again
return;
}
}
// send health to entity
EHealth eHealth;
eHealth.fHealth = m_fValue;
eHealth.bOverTopHealth = m_bOverTopHealth;
// if health is received
if (epass.penOther->ReceiveItem(eHealth)) {
if(_pNetwork->IsPlayerLocal(epass.penOther))
{
switch (m_EhitType)
{
case HIT_PILL: IFeel_PlayEffect("PU_HealthPill"); break;
case HIT_SMALL: IFeel_PlayEffect("PU_HealthSmall"); break;
case HIT_MEDIUM:IFeel_PlayEffect("PU_HealthMedium"); break;
case HIT_LARGE: IFeel_PlayEffect("PU_HealthLarge"); break;
case HIT_SUPER: IFeel_PlayEffect("PU_HealthSuper"); break;
}
}
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soPick, m_iSoundComponent, SOF_3D);
m_fPickSoundLen = GetSoundLength(m_iSoundComponent);
if (!GetSP()->sp_bHealthArmorStays || m_bPickupOnce) {
jump CItem::ItemReceived();
}
}
return;
};
Main() {
Initialize(); // initialize base class
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

180
Sources/Entities/Huanman.es Normal file
View File

@ -0,0 +1,180 @@
325
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/HuanMan/Huanman.h"
%}
uses "Entities/EnemyBase";
%{
// info structure
static EntityInfo eiHuanman = {
EIBT_FLESH, 125.0f,
0.0f, 2.1f, 0.0f,
0.0f, 1.1f, 0.0f,
};
#define CLOSE_HIT 2.0f
#define FIRE FLOAT3D( 0.45f, 2.0f, -1.25f)
%}
class CHuanman : CEnemyBase {
name "Huanman";
thumbnail "Thumbnails\\Huanman.tbn";
properties:
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
10 model MODEL_HUANMAN "Models\\Enemies\\Huanman\\Huanman.mdl",
11 texture TEXTURE_HUANMAN "Models\\Enemies\\Huanman\\Huanman.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Huanman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Huanman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Huanman\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Huanman\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Huanman\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Huanman\\Sounds\\Death.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return &eiHuanman;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// huanman can't harm huanman
if (!IsOfClass(penInflictor, "Huanman")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
StartModelAnim(HUANMAN_ANIM_WOUND, 0);
return HUANMAN_ANIM_WOUND;
};
// death
INDEX AnimForDeath(void) {
StartModelAnim(HUANMAN_ANIM_DEATH, 0);
return HUANMAN_ANIM_DEATH;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(HUANMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(HUANMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void) {
StartModelAnim(HUANMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void) {
StartModelAnim(HUANMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
StartModelAnim(HUANMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
// 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);
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
Fire(EVoid) : CEnemyBase::Fire {
// fire projectile
StartModelAnim(HUANMAN_ANIM_ATTACK, 0);
autowait(0.4f);
ShootProjectile(PRT_HUANMAN_FIRE, FIRE, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.6f);
StandingAnim();
autowait(FRnd()/2 + _pTimer->TickQuantum);
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit {
// attack with spear
StartModelAnim(HUANMAN_ANIM_ATTACK, 0);
autowait(0.4f);
if (CalcDist(m_penEnemy) < CLOSE_HIT) {
// damage enemy
FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector;
vDirection.Normalize();
InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 7.5f, FLOAT3D(0, 0, 0), vDirection);
}
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
autowait(0.6f);
StandingAnim();
autowait(FRnd()/2 + _pTimer->TickQuantum);
return EReturn();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetHealth(100.0f);
m_fMaxHealth = 100.0f;
en_fDensity = 1100.0f;
// set your appearance
SetModel(MODEL_HUANMAN);
SetModelMainTexture(TEXTURE_HUANMAN);
StandingAnim();
// setup moving speed
m_fWalkSpeed = FRnd() + 3.0f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 50.0f);
m_fAttackRunSpeed = FRnd() + 5.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 600.0f);
m_fCloseRunSpeed = FRnd() + 5.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 600.0f);
// setup attack distances
m_fAttackDistance = 50.0f;
m_fCloseDistance = 2.0f;
m_fStopDistance = 1.7f;
m_fAttackFireTime = 3.0f;
m_fCloseFireTime = 3.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 80.0f;
m_fBodyParts = 4;
m_fDamageWounded = 20.0f;
m_iScore = 500;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

279
Sources/Entities/Item.es Normal file
View File

@ -0,0 +1,279 @@
800
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
%{
// used to render certain entities only for certain players (like picked items, etc.)
extern ULONG _ulPlayerRenderingMask;
%}
class export CItem : CMovableModelEntity {
name "Item";
thumbnail "";
features "HasName", "HasDescription", "IsTargetable", "CanBePredictable";
properties:
1 CTString m_strName "Name" 'N' = "Item",
2 CTString m_strDescription = "",
// class properties
5 FLOAT m_fValue = 0.0f, // value
6 FLOAT m_fRespawnTime = 0.0f, // respawn time
7 BOOL m_bRespawn "Respawn" 'R' = FALSE, // respawn item
8 CEntityPointer m_penTarget "Target" 'T' COLOR(C_dGRAY|0xFF), // target to trigger when crossed over
9 BOOL m_bPickupOnce "PickupOnce" 'P' = FALSE, // can be picked by only one player, triggers only when really picked
10 CSoundObject m_soPick, // sound channel
12 FLOAT m_fPickSoundLen = 0.0f,
14 BOOL m_bDropped = FALSE, // dropped by a player during a deathmatch game
15 INDEX m_ulPickedMask = 0, // mask for which players picked this item
components:
1 model MODEL_ITEM "Models\\Items\\ItemHolder\\ItemHolder.mdl",
functions:
virtual void AdjustDifficulty(void)
{
}
/* Adjust model mip factor if needed. */
void AdjustMipFactor(FLOAT &fMipFactor)
{
// adjust flare glow, to decrease power with how you get closer
CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_FLARE);
if( pamo != NULL)
{
FLOAT fRatio = (Clamp( fMipFactor, 5.0f, 7.0f)-5.0f)/2.0f;
UBYTE ubRatio = UBYTE(255*fRatio);
COLOR colMutiply = RGBToColor(ubRatio,ubRatio,ubRatio)|CT_OPAQUE;
pamo->amo_moModelObject.mo_colBlendColor = colMutiply;
}
// if never picked
if (m_ulPickedMask==0) {
// don't bother testing
return;
}
BOOL bFlare = TRUE;
// if current player has already picked this item
if (_ulPlayerRenderingMask&m_ulPickedMask) {
// if picked items are not rendered
extern INDEX plr_bRenderPicked;
if (!plr_bRenderPicked) {
// kill mip factor
fMipFactor = UpperLimit(0.0f);
}
// if picked item particles are not rendered
extern INDEX plr_bRenderPickedParticles;
if (!plr_bRenderPickedParticles) {
// kill flare
bFlare = FALSE;
}
}
// implement flare on/off ?
}
// check whether should render particles for this item
BOOL ShowItemParticles(void)
{
// if current player has already picked this item
if (_ulPlayerRenderingMask&m_ulPickedMask) {
// if picked item particles are not rendered
extern INDEX plr_bRenderPickedParticles;
if (!plr_bRenderPickedParticles) {
// don't render
return FALSE;
}
}
// otherwise, render
return TRUE;
}
// check if given player already picked this item, and mark if not
BOOL MarkPickedBy(CEntity *pen)
{
if (!IsOfClass(pen, "Player")) {
return FALSE;
}
INDEX iPlayer = ((CPlayerEntity*)pen)->GetMyPlayerIndex();
BOOL bPickedAlready = (1<<iPlayer)&m_ulPickedMask;
m_ulPickedMask |= (1<<iPlayer);
return bPickedAlready;
}
// get maximum allowed range for predicting this entity
FLOAT GetPredictionRange(void)
{
extern FLOAT cli_fPredictItemsRange;
return cli_fPredictItemsRange;
}
/* Adjust model shading parameters if needed. */
BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient)
{
// in DM, glares are off, so add some light to items
//if( m_bRespawn)
{
// fixed light and ambient
colLight = 0x40404040;
colAmbient = 0x60606060;
}
/*
else
{
// fixed light and ambient
colLight = 0x30303030;
colAmbient = 0x30303030;
}
*/
// light direction always from upper left corner relative to the object
vLightDirection = FLOAT3D(-1,-1,-1);
vLightDirection.Normalize();
vLightDirection*=GetRotationMatrix();
// no shadow
return FALSE;
};
/************************************************************
* INITALIZATION *
************************************************************/
void Initialize(void) {
InitAsModel();
SetFlags(GetFlags()|ENF_SEETHROUGH);
SetPhysicsFlags(EPF_MODEL_SLIDING);
SetCollisionFlags(ECF_ITEM);
// make items not slide that much
en_fDeceleration = 60.0f;
// set appearance
SetModel(MODEL_ITEM);
SetDesiredTranslation(FLOAT3D(0,0,0)); // just to add to movers
};
/************************************************************
* SET MODEL AND ATTACHMENT *
************************************************************/
// Add item
void AddItem(ULONG ulIDModel, ULONG ulIDTexture,
ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) {
AddAttachmentToModel(this, *GetModelObject(), ITEMHOLDER_ATTACHMENT_ITEM, ulIDModel, ulIDTexture,
ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture);
};
void AddItemSpecial(INDEX iAttachmentPos, ULONG ulIDModel, ULONG ulIDTexture,
ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) {
AddAttachmentToModel(this, *GetModelObject(), iAttachmentPos, ulIDModel, ulIDTexture,
ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture);
};
// Add attachment to item
void AddItemAttachment(INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture,
ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) {
CModelObject &mo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject;
AddAttachmentToModel(this, mo, iAttachment, ulIDModel, ulIDTexture,
ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture);
};
// set animation of attachment
void SetItemAttachmentAnim(INDEX iAttachment, INDEX iAnim)
{
CModelObject &mo =
GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject.
GetAttachmentModel(iAttachment)->amo_moModelObject;
mo.PlayAnim(iAnim, 0);
}
// Add flare
void AddFlare(ULONG ulIDModel, ULONG ulIDTexture,
const FLOAT3D &vPos, const FLOAT3D &vStretch)
{
// add flare to items if not respawn
if( !m_bRespawn && !m_bDropped)
{
AddAttachmentToModel(this, *GetModelObject(),
ITEMHOLDER_ATTACHMENT_FLARE, ulIDModel, ulIDTexture, 0,0,0);
CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_FLARE);
amo.amo_moModelObject.StretchModel(vStretch);
amo.amo_plRelative.pl_PositionVector = vPos;
}
};
// Stretch item
void StretchItem(const FLOAT3D &vStretch) {
CModelObject &mo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject;
mo.StretchModel(vStretch);
ModelChangeNotify();
};
procedures:
/************************************************************
* VIRTUAL PROCEDURES THAT NEED OVERRIDE *
************************************************************/
ItemCollected(EPass epass) { return; };
/************************************************************
* I T E M L O O P *
************************************************************/
ItemLoop(EVoid) {
autowait(0.1f);
SetPredictable(TRUE);
AdjustDifficulty();
wait() {
on (EBegin) : { resume; }
on (EPass epass) : {
if (!IsOfClass(epass.penOther, "Player")) {
pass;
}
if (!m_bPickupOnce) {
SendToTarget(m_penTarget, EET_TRIGGER, epass.penOther);
m_penTarget = NULL;
}
call ItemCollected(epass);
}
on (EEnd) : { stop; }
}
// wait for sound to end
autowait(m_fPickSoundLen+0.5f);
// cease to exist
Destroy();
return;
};
ItemReceived(EVoid) {
// hide yourself
SwitchToEditorModel();
if (m_bPickupOnce) {
SendToTarget(m_penTarget, EET_TRIGGER, NULL);
}
// respawn item
if (m_bRespawn) {
ASSERT(m_fRespawnTime>0.0f);
// wait to respawn
wait(m_fRespawnTime) {
on (EBegin) : { resume; }
on (ETimer) : { stop; }
otherwise() : { resume; }
}
// show yourself
SwitchToModel();
// cease to exist
} else {
return EEnd();
}
return;
};
};

350
Sources/Entities/KeyItem.es Normal file
View File

@ -0,0 +1,350 @@
805
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
uses "Entities/Item";
// key type
enum KeyItemType {
0 KIT_ANKHWOOD "Wooden ankh",
1 KIT_ANKHROCK "Stone ankh",
2 KIT_ANKHGOLD "Gold ankh",
3 KIT_AMONGOLD "Gold amon",
4 KIT_ANKHGOLDDUMMY "Gold ankh dummy key",
5 KIT_ELEMENTEARTH "Element - Earth",
6 KIT_ELEMENTWATER "Element - Water",
7 KIT_ELEMENTAIR "Element - Air",
8 KIT_ELEMENTFIRE "Element - Fire",
9 KIT_RAKEY "Ra Key",
10 KIT_MOONKEY "Moon Key",
12 KIT_EYEOFRA "Eye of Ra",
13 KIT_SCARAB "Scarab",
14 KIT_COBRA "Cobra",
15 KIT_SCARABDUMMY "Scarab dummy",
16 KIT_HEART "Gold Heart",
17 KIT_FEATHER "Feather of Truth",
18 KIT_SPHINX1 "Sphinx 1",
19 KIT_SPHINX2 "Sphinx 2",
};
// event for sending through receive item
event EKey {
enum KeyItemType kitType,
};
%{
const char *GetKeyName(enum KeyItemType kit)
{
switch(kit) {
case KIT_ANKHWOOD : return TRANS("Wooden ankh"); break;
case KIT_ANKHROCK: return TRANS("Stone ankh"); break;
case KIT_ANKHGOLD :
case KIT_ANKHGOLDDUMMY : return TRANS("Gold ankh"); break;
case KIT_AMONGOLD : return TRANS("Gold Amon statue"); break;
case KIT_ELEMENTEARTH : return TRANS("Earth element"); break;
case KIT_ELEMENTWATER : return TRANS("Water element"); break;
case KIT_ELEMENTAIR : return TRANS("Air element"); break;
case KIT_ELEMENTFIRE : return TRANS("Fire element"); break;
case KIT_RAKEY : return TRANS("Ra key"); break;
case KIT_MOONKEY : return TRANS("Moon key"); break;
case KIT_EYEOFRA : return TRANS("Eye of Ra"); break;
case KIT_SCARAB :
case KIT_SCARABDUMMY : return TRANS("Scarab"); break;
case KIT_COBRA : return TRANS("Cobra"); break;
case KIT_HEART : return TRANS("Gold Heart"); break;
case KIT_FEATHER : return TRANS("Feather of Truth"); break;
case KIT_SPHINX1 :
case KIT_SPHINX2 : return TRANS("Gold Sphinx"); break;
default: return TRANS("unknown item"); break;
};
}
%}
class CKeyItem : CItem {
name "KeyItem";
thumbnail "Thumbnails\\KeyItem.tbn";
features "IsImportant";
properties:
1 enum KeyItemType m_kitType "Type" 'Y' = KIT_ANKHWOOD, // key type
3 INDEX m_iSoundComponent = 0,
components:
0 class CLASS_BASE "Classes\\Item.ecl",
// ********* ANKH KEY *********
1 model MODEL_ANKHWOOD "Models\\Items\\Keys\\AnkhWood\\Ankh.mdl",
2 texture TEXTURE_ANKHWOOD "Models\\Ages\\Egypt\\Vehicles\\BigBoat\\OldWood.tex",
3 model MODEL_ANKHROCK "Models\\Items\\Keys\\AnkhStone\\Ankh.mdl",
4 texture TEXTURE_ANKHROCK "Models\\Items\\Keys\\AnkhStone\\Stone.tex",
5 model MODEL_ANKHGOLD "Models\\Items\\Keys\\AnkhGold\\Ankh.mdl",
6 texture TEXTURE_ANKHGOLD "Models\\Items\\Keys\\AnkhGold\\Ankh.tex",
7 model MODEL_AMONGOLD "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.mdl",
8 texture TEXTURE_AMONGOLD "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.tex",
10 model MODEL_ELEMENTAIR "Models\\Items\\Keys\\Elements\\Air.mdl",
11 texture TEXTURE_ELEMENTAIR "Models\\Items\\Keys\\Elements\\Air.tex",
20 model MODEL_ELEMENTWATER "Models\\Items\\Keys\\Elements\\Water.mdl",
21 texture TEXTURE_ELEMENTWATER "Models\\Items\\Keys\\Elements\\Water.tex",
30 model MODEL_ELEMENTFIRE "Models\\Items\\Keys\\Elements\\Fire.mdl",
31 texture TEXTURE_ELEMENTFIRE "Models\\Items\\Keys\\Elements\\Fire.tex",
40 model MODEL_ELEMENTEARTH "Models\\Items\\Keys\\Elements\\Earth.mdl",
41 texture TEXTURE_ELEMENTEARTH "Models\\Items\\Keys\\Elements\\Texture.tex",
50 model MODEL_RAKEY "Models\\Items\\Keys\\RaKey\\Key.mdl",
51 texture TEXTURE_RAKEY "Models\\Items\\Keys\\RaKey\\Key.tex",
60 model MODEL_MOONKEY "Models\\Items\\Keys\\RaSign\\Sign.mdl",
61 texture TEXTURE_MOONKEY "Models\\Items\\Keys\\RaSign\\Sign.tex",
70 model MODEL_EYEOFRA "Models\\Items\\Keys\\EyeOfRa\\EyeOfRa.mdl",
71 texture TEXTURE_EYEOFRA "Models\\Items\\Keys\\EyeOfRa\\EyeOfRa.tex",
80 model MODEL_SCARAB "Models\\Items\\Keys\\Scarab\\Scarab.mdl",
81 texture TEXTURE_SCARAB "Models\\Items\\Keys\\Scarab\\Scarab.tex",
90 model MODEL_COBRA "Models\\Items\\Keys\\Uaset\\Uaset.mdl",
91 texture TEXTURE_COBRA "Models\\Items\\Keys\\Uaset\\Uaset.tex",
92 model MODEL_FEATHER "Models\\Items\\Keys\\Luxor\\FeatherOfTruth.mdl",
93 texture TEXTURE_FEATHER "Models\\Items\\Keys\\Luxor\\FeatherOfTruth.tex",
94 model MODEL_HEART "Models\\Items\\Keys\\Luxor\\GoldHeart.mdl",
95 texture TEXTURE_HEART "Models\\Items\\Keys\\Luxor\\GoldHeart.tex",
96 model MODEL_SPHINXGOLD "Models\\Items\\Keys\\GoldSphinx\\GoldSphinx.mdl",
97 texture TEXTURE_SPHINXGOLD "Models\\Items\\Keys\\GoldSphinx\\Sphinx.tex",
// ********* MISC *********
255 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
256 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
257 texture TEX_REFL_GOLD01 "Models\\ReflectionTextures\\Gold01.tex",
258 texture TEX_REFL_METAL01 "Models\\ReflectionTextures\\LightMetal01.tex",
259 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex",
260 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex",
// ************** SOUNDS **************
301 sound SOUND_KEY "Sounds\\Items\\Key.wav",
functions:
void Precache(void) {
PrecacheSound(SOUND_KEY);
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_strName = GetKeyName(m_kitType);
pes->es_ctCount = 1;
pes->es_ctAmmount = 1;
pes->es_fValue = 1;
pes->es_iScore = 0;//m_iScore;
return TRUE;
}
// render particles
void RenderParticles(void) {
// no particles when not existing
if (GetRenderType()!=CEntity::RT_MODEL) {
return;
}
switch (m_kitType) {
case KIT_ANKHWOOD:
case KIT_ANKHROCK:
case KIT_ANKHGOLD:
case KIT_ANKHGOLDDUMMY:
default:
Particles_Stardust(this, 0.9f, 0.70f, PT_STAR08, 32);
break;
case KIT_AMONGOLD:
Particles_Stardust(this, 1.6f, 1.00f, PT_STAR08, 32);
break;
}
}
// set health properties depending on type
void SetProperties(void) {
m_fRespawnTime = 10.0f;
m_strDescription = GetKeyName(m_kitType);
switch (m_kitType) {
case KIT_ANKHWOOD:
// set appearance
AddItem(MODEL_ANKHWOOD, TEXTURE_ANKHWOOD, 0, 0, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ANKHROCK:
// set appearance
AddItem(MODEL_ANKHROCK, TEXTURE_ANKHROCK, 0, 0, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ANKHGOLD:
case KIT_ANKHGOLDDUMMY:
// set appearance
AddItem(MODEL_ANKHGOLD, TEXTURE_ANKHGOLD, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_SPHINX1:
case KIT_SPHINX2:
// set appearance
AddItem(MODEL_SPHINXGOLD, TEXTURE_SPHINXGOLD, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_AMONGOLD:
// set appearance
AddItem(MODEL_AMONGOLD, TEXTURE_AMONGOLD, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(2,2,0.3f) );
StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ELEMENTEARTH:
// set appearance
AddItem(MODEL_ELEMENTEARTH, TEXTURE_ELEMENTEARTH, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ELEMENTAIR:
// set appearance
AddItem(MODEL_ELEMENTAIR, TEXTURE_ELEMENTAIR, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ELEMENTWATER:
// set appearance
AddItem(MODEL_ELEMENTWATER, TEXTURE_ELEMENTWATER, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_ELEMENTFIRE:
// set appearance
AddItem(MODEL_ELEMENTFIRE, TEXTURE_ELEMENTFIRE, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_RAKEY:
// set appearance
AddItem(MODEL_RAKEY, TEXTURE_RAKEY, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_MOONKEY:
// set appearance
AddItem(MODEL_MOONKEY, TEXTURE_MOONKEY, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_EYEOFRA:
// set appearance
AddItem(MODEL_EYEOFRA, TEXTURE_EYEOFRA, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_SCARAB:
case KIT_SCARABDUMMY:
// set appearance
AddItem(MODEL_SCARAB, TEXTURE_SCARAB, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_COBRA:
// set appearance
AddItem(MODEL_COBRA, TEXTURE_COBRA, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_FEATHER:
// set appearance
AddItem(MODEL_FEATHER, TEXTURE_FEATHER, 0, 0, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
case KIT_HEART:
// set appearance
AddItem(MODEL_HEART, TEXTURE_HEART, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
break;
}
};
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected {
ASSERT(epass.penOther!=NULL);
// send key to entity
EKey eKey;
eKey.kitType = m_kitType;
// if health is received
if (epass.penOther->ReceiveItem(eKey)) {
if(_pNetwork->IsPlayerLocal(epass.penOther)) {IFeel_PlayEffect("PU_Key");}
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soPick, m_iSoundComponent, SOF_3D);
m_fPickSoundLen = GetSoundLength(m_iSoundComponent);
jump CItem::ItemReceived();
}
return;
};
Main() {
Initialize(); // initialize base class
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL);
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

View File

@ -0,0 +1,5 @@
Last ES ID number:
Enemies: 341 (CreateRider)
Tools: 232 (Counter)
Items: 807 (MessageItem)

454
Sources/Entities/Light.es Normal file
View File

@ -0,0 +1,454 @@
200
%{
#include "Entities/StdH/StdH.h"
%}
uses "Entities/ModelDestruction";
uses "Entities/AnimationChanger";
enum LightType {
0 LT_POINT "Point light",
1 LT_AMBIENT "Ambient light",
2 LT_STRONG_AMBIENT "Strong ambient light",
3 LT_DIRECTIONAL "Directional light",
4 LT_STRONG_POINT "Strong point light",
};
enum LensFlareType {
0 LFT_NONE "None",
1 LFT_STANDARD "Standard",
2 LFT_STANDARD_REFLECTIONS "Standard reflections",
3 LFT_YELLOW_STAR_RED_RING "Yellow star with red ring",
4 LFT_WHITE_GLOW_STAR_RED_RING "White glow star with red ring",
5 LFT_WHITE_GLOW_STAR "White glow star",
6 LFT_WHITE_STAR_RED_RING_STREAKS "White star with red ring and streaks",
7 LFT_WHITE_STAR_RED_REFLECTIONS "White star with red reflections",
8 LFT_BLUE_STAR_BLUE_REFLECTIONS "Blue star with blue reflections",
9 LFT_PV_SPACE_SHIP_WINDOW_FLARE "Pyramid valley space ship window flare",
10 LFT_WHITE_GLOW_STAR_RED_RING_FAR "Yellow star with red ring far",
11 LFT_WHITE_GLOW_FAR "White glow far",
12 LFT_WHITE_GLOW_STAR_NG "White glow star no glare",
};
%{
void CLight_OnInitClass(void)
{
// init lens flares effects
InitLensFlares();
}
void CLight_OnEndClass(void)
{
// close lens flares effects
CloseLensFlares();
}
%}
class CLight : CEntity {
name "Light";
thumbnail "Thumbnails\\Light.tbn";
features "HasName", "HasDescription", "ImplementsOnInitClass", "ImplementsOnEndClass";
properties:
2 COLOR m_colColor "Color" 'C' =C_GRAY,
9 COLOR m_colAmbient "Directional ambient" 'E' =C_BLACK,
1 RANGE m_rFallOffRange "Fall-off" 'F' =8.0f features(EPROPF_HIDEINPERSPECTIVE),
4 RANGE m_rHotSpotRange "Hot-spot" 'H' =0.0f features(EPROPF_HIDEINPERSPECTIVE),
7 ILLUMINATIONTYPE m_itIllumination "Polygon illumination" 'I' =0,
8 enum LightType m_ltType "Type" 'Y' =LT_POINT,
10 CTString m_strDescription = "",
11 CTString m_strName "Name" 'N' = "Light",
12 BOOL m_bDarkLight "Dark light" 'A' = FALSE,
13 FLOAT m_fNearClip "Clip near" = 0.1f,
14 FLOAT m_fFarClip "Clip far" = 0.01f,
15 BOOL m_bSubstractSectorAmbient "Substract sector ambient" 'S' = FALSE,
16 BOOL m_bRenderAsSmallLight "Render as small" 'R' = FALSE,
17 enum LensFlareType m_lftLensFlare "Lens flare" 'L' = LFT_NONE,
18 BOOL m_bBackground "Background" 'B' = FALSE,
19 BOOL m_bLensFlareOnly "Lens flare only" 'O' = FALSE,
20 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""),
21 ANIMATION m_iLightAnimation "Light animation" = 0,
25 FLOAT m_tmOffsetPhase "Light animation offset" = 0.0f,
22 CAnimObject m_aoLightAnimation,
24 BOOL m_bTargetable "Targetable" = FALSE,
26 BOOL m_bDynamic "Dynamic" = FALSE,
27 BOOL m_bDiffusion "Diffusion" 'D' = TRUE,
30 CTFileName m_fnmAmbientLightAnimation "Ambient light animation file" = CTString(""),
31 ANIMATION m_iAmbientLightAnimation "Ambient light animation" = 0,
32 CAnimObject m_aoAmbientLightAnimation,
{
CLightSource m_lsLightSource;
CBoolDefaultFalse m_bdfInitialized; // set if already initialized once
}
components:
1 model MODEL_LIGHT_SOURCE "Models\\Editor\\LightSource.mdl",
2 texture TEXTURE_POINT_LIGHT "Models\\Editor\\PointLight.tex",
3 texture TEXTURE_AMBIENT_LIGHT "Models\\Editor\\AmbientLight.tex",
4 texture TEXTURE_REAL_AMBIENT_LIGHT "Models\\Editor\\RealAmbientLight.tex",
5 model MODEL_SPOT_LIGHT "Models\\Editor\\SpotLight.mdl",
6 texture TEXTURE_SPOT_LIGHT "Models\\Editor\\SpotLight.tex",
functions:
/* Get anim data for given animation property - return NULL for none. */
CAnimData *GetAnimData(SLONG slPropertyOffset)
{
if (slPropertyOffset==offsetof(CLight, m_iLightAnimation))
{
return m_aoLightAnimation.GetData();
}
else if (slPropertyOffset==offsetof(CLight, m_iAmbientLightAnimation))
{
return m_aoAmbientLightAnimation.GetData();
}
else
{
return CEntity::GetAnimData(slPropertyOffset);
}
};
BOOL IsTargetable(void) const
{
return m_bTargetable;
}
BOOL IsImportant(void) const
{
return(m_ltType==LT_DIRECTIONAL);
}
/* Handle an event, return false if the event is not handled. */
BOOL HandleEvent(const CEntityEvent &ee)
{
// when someone in range is destroyed
if (ee.ee_slEvent==EVENTCODE_ERangeModelDestruction)
{
// fade out completely
m_colColor = C_BLACK;
m_colAmbient = C_BLACK;
CLightSource lsNew;
SetupLightSource(lsNew);
m_lsLightSource.SetLightSource(lsNew);
return TRUE;
// when animation should be changed
}
else if (ee.ee_slEvent==EVENTCODE_EChangeAnim)
{
EChangeAnim &eChange = (EChangeAnim &)ee;
// for diffuse component of light
m_iLightAnimation = eChange.iLightAnim;
if (m_aoLightAnimation.GetData()!=NULL)
{
m_aoLightAnimation.PlayAnim(m_iLightAnimation, eChange.bLightLoop?AOF_LOOPING:0);
}
// for ambient component of light
m_iAmbientLightAnimation = eChange.iAmbientLightAnim;
if (m_aoAmbientLightAnimation.GetData()!=NULL)
{
m_aoAmbientLightAnimation.PlayAnim(m_iAmbientLightAnimation, eChange.bAmbientLightLoop?AOF_LOOPING:0);
}
// if neither ambient nor difuse animation is set, apply direct color change
if( (m_aoLightAnimation.GetData()==NULL) && (m_aoAmbientLightAnimation.GetData()==NULL) )
{
m_colColor = eChange.colDiffuse;
m_colAmbient = eChange.colAmbient;
CLightSource lsNew;
SetupLightSource(lsNew);
m_lsLightSource.SetLightSource(lsNew);
return TRUE;
}
}
return FALSE;
}
// apply mirror and stretch to the entity
void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX)
{
// stretch its ranges
m_rFallOffRange*=fStretch;
m_rHotSpotRange*=fStretch;
m_fNearClip *=fStretch;
m_fFarClip *=fStretch;
//(void)bMirrorX; // no mirror for lights
}
/* Get static light source information. */
CLightSource *GetLightSource(void)
{
// if never initialized before (happens after loading)
if (!m_bdfInitialized.bdf_bValue) {
// initialize now
CLightSource lsNew;
SetupLightSource(lsNew);
m_lsLightSource.SetLightSourceWithNoDiscarding(lsNew);
m_bdfInitialized.bdf_bValue = TRUE;
}
if (!IsPredictor()) {
return &m_lsLightSource;
} else {
return NULL;
}
}
// prepare and transfer light source variables
void SetupLightSource( CLightSource &lsNew)
{
switch( m_ltType) {
case LT_POINT:
case LT_STRONG_POINT:
lsNew.ls_ulFlags = LSF_CASTSHADOWS;
break;
case LT_DIRECTIONAL:
lsNew.ls_ulFlags = LSF_DIRECTIONAL|LSF_CASTSHADOWS;
break;
case LT_STRONG_AMBIENT:
case LT_AMBIENT:
lsNew.ls_ulFlags = 0;
break;
}
if( m_bSubstractSectorAmbient) { lsNew.ls_ulFlags |= LSF_SUBSTRACTSECTORAMBIENT; }
if( m_bLensFlareOnly) { lsNew.ls_ulFlags |= LSF_LENSFLAREONLY; }
if( m_bDynamic) { lsNew.ls_ulFlags |= LSF_DYNAMIC; }
// directional light cannot be dark
if( m_bDarkLight) {
if( m_ltType==LT_DIRECTIONAL) {
lsNew.ls_ulFlags &= ~LSF_DARKLIGHT;
m_bDarkLight = FALSE;
} else {
lsNew.ls_ulFlags |= LSF_DARKLIGHT;
}
}
// ambient and directional lights doesn't support diffusion
if( m_bDiffusion) {
if( m_bDynamic || m_ltType==LT_AMBIENT || m_ltType==LT_STRONG_AMBIENT) {
lsNew.ls_ulFlags &= ~LSF_DIFFUSION;
m_bDiffusion = FALSE;
} else {
lsNew.ls_ulFlags |= LSF_DIFFUSION;
}
}
lsNew.ls_rHotSpot = m_rHotSpotRange;
lsNew.ls_rFallOff = m_rFallOffRange;
lsNew.ls_fNearClipDistance = m_fNearClip;
lsNew.ls_fFarClipDistance = m_fFarClip;
// hot spot for strong lights is 90% of light range
if( m_ltType == LT_STRONG_AMBIENT || m_ltType == LT_STRONG_POINT) {
lsNew.ls_rHotSpot = lsNew.ls_rFallOff*0.9f;
}
lsNew.ls_colColor = m_colColor;
lsNew.ls_colAmbient = C_BLACK; // only directional lights are allowed to have ambient component
if( lsNew.ls_ulFlags&LSF_DIRECTIONAL) { lsNew.ls_colAmbient = m_colAmbient; }
lsNew.ls_ubPolygonalMask = (UBYTE) m_itIllumination;
switch(m_lftLensFlare)
{
case LFT_NONE:
lsNew.ls_plftLensFlare = NULL;
break;
case LFT_STANDARD:
lsNew.ls_plftLensFlare = &_lftStandard;
break;
case LFT_STANDARD_REFLECTIONS:
lsNew.ls_plftLensFlare = &_lftStandardReflections;
break;
case LFT_YELLOW_STAR_RED_RING:
lsNew.ls_plftLensFlare = &_lftYellowStarRedRing;
break;
case LFT_WHITE_GLOW_STAR_RED_RING:
lsNew.ls_plftLensFlare = &_lftWhiteGlowStarRedRing;
break;
case LFT_WHITE_GLOW_STAR:
lsNew.ls_plftLensFlare = &_lftWhiteGlowStar;
break;
case LFT_WHITE_STAR_RED_RING_STREAKS:
lsNew.ls_plftLensFlare = &_lftWhiteStarRedRingStreaks;
break;
case LFT_WHITE_STAR_RED_REFLECTIONS:
lsNew.ls_plftLensFlare = &_lftWhiteStarRedReflections;
break;
case LFT_BLUE_STAR_BLUE_REFLECTIONS:
lsNew.ls_plftLensFlare = &_lftBlueStarBlueReflections;
break;
case LFT_PV_SPACE_SHIP_WINDOW_FLARE:
lsNew.ls_plftLensFlare = &_lftPVSpaceShipWindowFlare;
break;
case LFT_WHITE_GLOW_STAR_RED_RING_FAR:
lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar;
break;
case LFT_WHITE_GLOW_FAR:
lsNew.ls_plftLensFlare = &_lftWhiteGlowFar;
break;
case LFT_WHITE_GLOW_STAR_NG:
lsNew.ls_plftLensFlare = &_lftWhiteGlowStarNG;
break;
}
// --------- Setup light animations
// diffuse
lsNew.ls_paoLightAnimation = NULL;
if (m_aoLightAnimation.GetData()!=NULL) {
lsNew.ls_paoLightAnimation = &m_aoLightAnimation;
}
// ambient
lsNew.ls_paoAmbientLightAnimation = NULL;
if (m_aoAmbientLightAnimation.GetData()!=NULL) {
lsNew.ls_paoAmbientLightAnimation = &m_aoAmbientLightAnimation;
}
}
procedures:
Main()
{
// fall off and hot spot must be positive values
if (m_rFallOffRange<0) {
m_rFallOffRange = 0.0f;
}
if (m_rHotSpotRange<0) {
m_rHotSpotRange = 0.0f;
}
// hot spot must be less or equal falloff
if (m_rHotSpotRange>m_rFallOffRange) {
m_rHotSpotRange = m_rFallOffRange;
}
// near clip must not be too small relatively to falloff
// (crashes on shadow rendering otherwise!)
//if (m_fNearClip<m_rFallOffRange*1E-4f) {
// m_fNearClip = m_rFallOffRange*1E-4f;
//}
// near clip must not be too small
if (m_fNearClip<=0.01f) {
m_fNearClip = 0.01f;
}
// far clip distance must be positive values
if (m_fFarClip<=0) {
m_fFarClip = 0.0f;//0.01f;
}
// only directional lights are allowed to have ambient component
if( m_ltType!=LT_DIRECTIONAL) {
m_colAmbient = C_BLACK;
}
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set model stretch -- MUST BE DONE BEFORE SETTING MODEL!
if( m_bRenderAsSmallLight)
{
GetModelObject()->mo_Stretch = FLOAT3D( 0.25f, 0.25f, 0.25f);
}
else
{
// set stretch factor of the light (directional lights don't have stretch)
if ( m_ltType != LT_DIRECTIONAL) {
const float LIGHT_MINSIZE=0.5f;
FLOAT fFactor = Log2(m_rFallOffRange)*LIGHT_MINSIZE;
if (fFactor<LIGHT_MINSIZE) {
fFactor=LIGHT_MINSIZE;
}
GetModelObject()->mo_Stretch = FLOAT3D( fFactor, fFactor, fFactor);
}
}
CTString strType;
if( m_ltType == LT_POINT || m_ltType == LT_STRONG_POINT)
{
strType = "point";
// set model to light source
SetModel(MODEL_LIGHT_SOURCE);
// set texture of point light model
SetModelMainTexture(TEXTURE_POINT_LIGHT);
}
// initialize ambient light
else if( m_ltType == LT_AMBIENT)
{
strType = "ambient";
// set model to light source
SetModel(MODEL_LIGHT_SOURCE);
// set texture of ambient light model
SetModelMainTexture(TEXTURE_AMBIENT_LIGHT);
}
// initialize real ambient light
else if( m_ltType == LT_STRONG_AMBIENT)
{
strType = "ambient";
// set model to light source
SetModel(MODEL_LIGHT_SOURCE);
// set texture of real ambient light model
SetModelMainTexture(TEXTURE_REAL_AMBIENT_LIGHT);
}
// initialize spot light
else if( m_ltType == LT_DIRECTIONAL)
{
strType = "directional";
// set model to spot light
SetModel(MODEL_SPOT_LIGHT);
// set texture of spot light model
SetModelMainTexture(TEXTURE_SPOT_LIGHT);
}
if( m_bDarkLight)
{
strType = strType+", dark";
}
// set diffuse light animation if available
try {
m_aoLightAnimation.SetData_t(m_fnmLightAnimation);
} catch (char *strError) {
WarningMessage(TRANS("Cannot load '%s': %s"), (const char*)(CTString&)m_fnmLightAnimation,(const char*) strError);
m_fnmLightAnimation = "";
}
if (m_aoLightAnimation.GetData()!=NULL) {
m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING);
m_aoLightAnimation.OffsetPhase(m_tmOffsetPhase*m_aoLightAnimation.GetCurrentAnimLength());
}
// set ambient light animation if available
try {
m_aoAmbientLightAnimation.SetData_t(m_fnmAmbientLightAnimation);
} catch (char *strError) {
WarningMessage(TRANS("Cannot load '%s': %s"), (const char*)(CTString&)m_fnmAmbientLightAnimation, (const char*) strError);
m_fnmAmbientLightAnimation = "";
}
if (m_aoAmbientLightAnimation.GetData()!=NULL) {
m_aoAmbientLightAnimation.PlayAnim(m_iAmbientLightAnimation, AOF_LOOPING);
m_aoAmbientLightAnimation.OffsetPhase(m_tmOffsetPhase*m_aoAmbientLightAnimation.GetCurrentAnimLength());
}
// set a new light source with light properties
CLightSource lsNew;
SetupLightSource(lsNew);
// setup background rendering flag
if (m_bBackground) {
SetFlags(GetFlags()|ENF_BACKGROUND);
} else {
SetFlags(GetFlags()&~ENF_BACKGROUND);
}
// set up this light source from the new properties
m_lsLightSource.ls_penEntity = this;
if (!m_bdfInitialized.bdf_bValue) {
m_lsLightSource.SetLightSourceWithNoDiscarding(lsNew);
m_bdfInitialized.bdf_bValue = TRUE;
} else {
m_lsLightSource.SetLightSource(lsNew);
}
m_strDescription.PrintF("%s:%g-%g",
(const char*)strType, m_rHotSpotRange, m_rFallOffRange);
return;
};
};

View File

@ -0,0 +1,33 @@
201
%{
#include "Entities/StdH/StdH.h"
%}
class CLightStyle : CEntity {
name "Light";
thumbnail "Models\\Editor\\LightStyle.tbn";
features "HasName", "IsTargetable";
properties:
2 CTString m_strName "Name" 'N' = "<light style>",
// 1 LIGHTANIMATION m_iLightAnimation "Light animation" 'A'
components:
1 model MODEL_LIGHTSTYLE "Models\\Editor\\LightSource.mdl",
2 texture TEXTURE_LIGHTSTYLE "Models\\Editor\\LightStyle.tex"
functions:
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_LIGHTSTYLE);
SetModelMainTexture(TEXTURE_LIGHTSTYLE);
return;
}
};

View File

@ -0,0 +1,258 @@
607
%{
#include "Entities/StdH/StdH.h"
#include "Entities/BackgroundViewer.h"
#include "Entities/WorldSettingsController.h"
#include "Entities/Light.h"
%}
%{
struct ThunderInfo
{
INDEX ti_iSound;
FLOAT ti_fThunderStrikeDelay;
};
struct ThunderInfo _atiThunderSounds[3] =
{
{ SOUND_THUNDER1, 0.6f},
{ SOUND_THUNDER2, 0.0f},
{ SOUND_THUNDER3, 0.0f},
};
%}
class CLightning: CMovableModelEntity {
name "Lightning";
thumbnail "Thumbnails\\Lightning.tbn";
features "IsTargetable", "HasName";
properties:
1 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BLUE|0xFF), // ptr to lightninig target
2 CEntityPointer m_penwsc, // ptr to world settings controller
3 CTString m_strName "Name" 'N' = "Lightning", // class name
4 FLOAT m_tmLightningStart = -1.0f, // lightning start time
5 CSoundObject m_soThunder, // sound channel
6 BOOL m_bBackground "Background" 'B' =FALSE,
7 CEntityPointer m_penLight "Light" 'L' COLOR(C_CYAN|0xFF), // ptr to light
8 ANIMATION m_iLightAnim "Light Animation" 'A' = 0,
9 INDEX m_iSoundPlaying = 0,
10 FLOAT m_fLightningPower "Lightning power" 'P' = 1.0f, // lightning's ligting power
11 FLOAT m_fSoundDelay "Sound delay" 'D' = 0.0f, // thunder's delay
components:
1 model MODEL_TELEPORT "Models\\Editor\\Teleport.mdl",
2 texture TEXTURE_TELEPORT "Models\\Editor\\BoundingBox.tex",
3 sound SOUND_THUNDER1 "Sounds\\Environment\\Thunders\\Thunder1.wav",
4 sound SOUND_THUNDER2 "Sounds\\Environment\\Thunders\\Thunder2.wav",
5 sound SOUND_THUNDER3 "Sounds\\Environment\\Thunders\\Thunder3.wav",
functions:
void Precache(void)
{
CMovableModelEntity::Precache();
PrecacheSound(SOUND_THUNDER1);
PrecacheSound(SOUND_THUNDER2);
PrecacheSound(SOUND_THUNDER3);
}
/* Get anim data for given animation property - return NULL for none. */
CAnimData *GetAnimData(SLONG slPropertyOffset)
{
if (m_penLight==NULL) {
return NULL;
}
// if light entity
if (IsOfClass(m_penLight, "Light"))
{
CLight *penLight = (CLight*)&*m_penLight;
if (slPropertyOffset==offsetof(CLightning, m_iLightAnim))
{
return penLight->m_aoLightAnimation.GetData();
}
}
else
{
WarningMessage("Target '%s' is not of light class!", (const char*)m_penLight->GetName());
}
return NULL;
};
void RenderParticles(void)
{
if( m_penTarget==NULL) {return;};
TIME tmNow = _pTimer->GetLerpedCurrentTick();
// if lightning is traveling
if(
((tmNow-m_tmLightningStart) > 0.0f) &&
((tmNow-m_tmLightningStart) < 1.5f) )
{
// render lightning particles
FLOAT3D vSrc = GetPlacement().pl_PositionVector;
FLOAT3D vDst = m_penTarget->GetPlacement().pl_PositionVector;
Particles_Lightning( vSrc, vDst, m_tmLightningStart);
}
}
procedures:
LightningStike()
{
// choose random sound
m_iSoundPlaying = 1+IRnd()%( ARRAYCOUNT(_atiThunderSounds)-1);
if( m_fSoundDelay != 0)
{
m_iSoundPlaying=0;
}
m_soThunder.SetVolume(1.5f*m_fLightningPower, 1.5f*m_fLightningPower);
m_soThunder.SetPitch(Lerp(0.9f, 1.2f, FRnd()));
if( m_fSoundDelay == 0.0f)
{
// play thunder !
PlaySound(m_soThunder, _atiThunderSounds[ m_iSoundPlaying].ti_iSound, 0);
}
// wait for sound to progress to lightning strike
autowait( _atiThunderSounds[ m_iSoundPlaying].ti_fThunderStrikeDelay);
// remember current time as lightning start time
TIME tmNow = _pTimer->CurrentTick();
m_tmLightningStart = tmNow;
// also in world settings controller
((CWorldSettingsController *)&*m_penwsc)->m_tmLightningStart = tmNow;
// set power of lightning
((CWorldSettingsController *)&*m_penwsc)->m_fLightningPower = m_fLightningPower;
// trigger light animation
if( m_penLight != NULL)
{
EChangeAnim eChange;
eChange.iLightAnim = m_iLightAnim;
eChange.bLightLoop = FALSE;
m_penLight->SendEvent(eChange);
}
if( m_fSoundDelay != 0.0f)
{
// wait given delay time
autowait( m_fSoundDelay);
// play thunder !
PlaySound(m_soThunder, _atiThunderSounds[ m_iSoundPlaying].ti_iSound, 0);
}
// wait until end of sound
wait( GetSoundLength(_atiThunderSounds[ m_iSoundPlaying].ti_iSound)-
_atiThunderSounds[ m_iSoundPlaying].ti_fThunderStrikeDelay)
{
on (ETimer) :
{
stop;
}
otherwise() :
{
resume;
};
}
return EBegin();
}
Main(EVoid)
{
// set appearance
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_TELEPORT);
SetModelMainTexture(TEXTURE_TELEPORT);
// see if it is lightning on background
if (m_bBackground)
{
SetFlags(GetFlags()|ENF_BACKGROUND);
}
else
{
SetFlags(GetFlags()&~ENF_BACKGROUND);
}
// obtain bcg viewer entity
CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer();
if( penBcgViewer == NULL)
{
// don't do anything
return;
}
// obtain world settings controller
m_penwsc = penBcgViewer->m_penWorldSettingsController;
if( m_penwsc == NULL)
{
// don't do anything
return;
}
// must be world settings controller entity
if (!IsOfClass(m_penwsc, "WorldSettingsController"))
{
// don't do anything
return;
}
// lightning target must be marker
if( (m_penTarget == NULL) || (!IsOfClass(m_penTarget, "Marker")) )
{
if( m_penTarget != NULL)
{
WarningMessage("Target '%s' is not of Marker class!", (const char*)m_penTarget->GetName());
}
// don't do anything
return;
}
// stretch model
FLOAT3D vDirection =
(m_penTarget->GetPlacement().pl_PositionVector-
GetPlacement().pl_PositionVector);
FLOAT3D vStretch = vDirection;
vStretch(1) = 1.0f;
vStretch(2) = 1.0f;
vStretch(3) = -vDirection.Length();
// set entity orientation
CPlacement3D pl = GetPlacement();
DirectionVectorToAngles(vDirection.Normalize(), pl.pl_OrientationAngle);
SetPlacement(pl);
GetModelObject()->StretchModel(vStretch);
ModelChangeNotify();
// correct power factor to fall under 0-1 boundaries
m_fLightningPower = Clamp( m_fLightningPower, 0.0f, 1.0f);
// spawn in world editor
autowait(0.1f);
while (TRUE)
{
wait()
{
on (EBegin) : { resume; }
on (ETrigger eTrigger) :
{
call LightningStike();
resume;
}
otherwise() :
{
resume;
};
};
}
}
};

452
Sources/Entities/Mamut.es Normal file
View File

@ -0,0 +1,452 @@
327
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/Mamut/MAMUT.H"
#include "Models/Enemies/MAMUTMAN/Mamutman.h"
%}
uses "Entities/EnemyBase";
uses "Entities/Mamutman";
uses "Entities/AirWave";
uses "Entities/Bullet";
enum MamutChar {
0 MAT_SUMMER "Summer",
1 MAT_WINTER "Winter",
};
%{
// info structure
static EntityInfo eiMamut = {
EIBT_FLESH, 2500.0f,
0.0f, 1.5f, 0.0f,
0.0f, 2.0f, 0.0f,
};
#define HIT_DISTANCE 13.0f
#define FIRE_BULLET FLOAT3D(0.0f*2, 4.0f*2, -4.0f*2)
#define FIRE_AIRWAVE FLOAT3D(0.0f*2, 0.5f*2, -4.0f*2)
#define RIDER_FRONT FLOAT3D( 0.25f*2, 6.5f*2, 0.5f*2)
#define RIDER_MIDDLE FLOAT3D(-0.25f*2, 5.6f*2, 1.5f*2)
#define RIDER_REAR FLOAT3D( 0.1f*2, 4.6f*2, 2.4f*2)
%}
class CMamut : CEnemyBase {
name "Mamut";
thumbnail "Thumbnails\\Mamut.tbn";
properties:
1 enum MamutChar m_EmcChar "Character" 'C' = MAT_SUMMER, // character
2 BOOL m_bFrontRider "Rider Front" 'H' = FALSE, // front rider
3 BOOL m_bMiddleRider "Rider Middle" 'J' = FALSE, // middle rider
4 BOOL m_bRearRider "Rider Rear" 'K' = FALSE, // rear rider
5 CEntityPointer m_penBullet, // bullet
6 FLOAT m_fLastShootTime = 0.0f,
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
1 class CLASS_BULLET "Classes\\Bullet.ecl",
2 class CLASS_MAMUTMAN "Classes\\Mamutman.ecl",
3 class CLASS_AIRWAVE "Classes\\AirWave.ecl",
10 model MODEL_MAMUT "Models\\Enemies\\Mamut\\Mamut.mdl",
11 texture TEXTURE_MAMUT_SUMMER "Models\\Enemies\\Mamut\\Mamut.tex",
12 texture TEXTURE_MAMUT_WINTER "Models\\Enemies\\Mamut\\Mamut3.tex",
20 model MODEL_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.mdl",
21 texture TEXTURE_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Mamut\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Mamut\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Mamut\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Mamut\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Mamut\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Mamut\\Sounds\\Death.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return &eiMamut;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// mamut can't harm mamut
if (!IsOfClass(penInflictor, "Mamut")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// play attachmnet anim
void PlayAttachmentAnim(INDEX iAttachment, INDEX iAnim, ULONG ulFlags) {
CAttachmentModelObject *amo = GetModelObject()->GetAttachmentModel(iAttachment);
if (amo!=NULL) {
amo->amo_moModelObject.PlayAnim(iAnim, ulFlags);
}
};
// death
INDEX AnimForDeath(void) {
StartModelAnim(MAMUT_ANIM_DEATH, 0);
return MAMUT_ANIM_DEATH;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(MAMUT_COLLISION_BOX_DEATH);
DropRiders(TRUE);
};
// drop riders
void CreateRider(const FLOAT3D &vPos, INDEX iRider) {
// mamutman start position
CPlacement3D pl;
pl.pl_OrientationAngle = ANGLE3D(0,0,0);
pl.pl_PositionVector = vPos;
pl.RelativeToAbsolute(GetPlacement());
// create rider
CEntityPointer pen = CreateEntity(pl, CLASS_MAMUTMAN);
((CMamutman&)*pen).m_bSpawned = TRUE;
((CMamutman&)*pen).m_bSpawnedPosition = iRider;
((CMamutman&)*pen).m_penEnemy = m_penEnemy;
((CMamutman&)*pen).m_ttTarget = m_ttTarget;
pen->Initialize(EVoid());
};
void DropRiders(BOOL bAlways) {
if (m_bFrontRider && (bAlways || (IRnd()&1))) {
m_bFrontRider = FALSE;
CreateRider(RIDER_FRONT, 0);
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT);
}
if (m_bMiddleRider && (bAlways || (IRnd()&1))) {
m_bMiddleRider = FALSE;
CreateRider(RIDER_MIDDLE, 1);
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE);
}
if (m_bRearRider && (bAlways || (IRnd()&1))) {
m_bRearRider = FALSE;
CreateRider(RIDER_REAR, 2);
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR);
}
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(MAMUT_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_STANDMOUNTEDFIRST, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_STANDMOUNTEDSECOND, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_STANDMOUNTEDTHIRD, 0);
};
void WalkingAnim(void) {
StartModelAnim(MAMUT_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDWALKFIRST, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDWALKSECOND, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDWALKTHIRD, 0);
};
void RunningAnim(void) {
StartModelAnim(MAMUT_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDRUNFIRST, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDRUNSECOND, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDRUNTHIRD, 0);
};
void RotatingAnim(void) {
StartModelAnim(MAMUT_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDWALKFIRST, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDWALKSECOND, 0);
PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDWALKTHIRD, 0);
};
// 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);
};
/************************************************************
* FIRE BULLET *
************************************************************/
// prepare bullet
void PrepareBullet(void) {
// bullet start position
CPlacement3D plBullet;
plBullet.pl_OrientationAngle = ANGLE3D(0,0,0);
plBullet.pl_PositionVector = FIRE_BULLET;
plBullet.RelativeToAbsolute(GetPlacement());
// create bullet
m_penBullet = CreateEntity(plBullet, CLASS_BULLET);
// init bullet
EBulletInit eInit;
eInit.penOwner = this;
eInit.fDamage = 1.0f;
m_penBullet->Initialize(eInit);
((CBullet&)*m_penBullet).CalcTarget(m_penEnemy, 100);
};
// fire bullet
void FireBullet(void) {
((CBullet&)*m_penBullet).LaunchBullet(TRUE, TRUE, TRUE);
((CBullet&)*m_penBullet).DestroyBullet();
};
// fire air wave
void FireAirWave(void) {
// target enemy body
EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo());
FLOAT3D vShootTarget;
GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget);
// launch
CPlacement3D pl;
PrepareFreeFlyingProjectile(pl, vShootTarget, FIRE_AIRWAVE, ANGLE3D(0, 0, 0));
CEntityPointer penProjectile = CreateEntity(pl, CLASS_AIRWAVE);
EAirWave eLaunch;
eLaunch.penLauncher = this;
penProjectile->Initialize(eLaunch);
};
procedures:
/************************************************************
* PROCEDURES WHEN HARMED *
************************************************************/
// Play wound animation and falling body part
BeWounded(EDamage eDamage) : CEnemyBase::BeWounded
{
StopMoving();
// damage anim
StartModelAnim(MAMUT_ANIM_WOUND02, 0);
autowait(0.5f);
// drop riders
if (GetHealth()<600.0f) {
DropRiders(GetHealth()<250.0f);
}
autowait(1.5f);
return EReturn();
};
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
/* // initial preparation
InitializeAttack(EVoid) : CEnemyBase::InitializeAttack {
m_fLastShootTime = 0.0f;
jump CEnemyBase::InitializeAttack();
};
// attack shoot
AttackShoot() : CEnemyBase::AttackShoot {
// shoot at enemy if possible
if (CanAttackEnemy(m_penEnemy, Cos(AngleDeg(130.0f)))) {
// set next shoot time
m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/3.0f);
// fire
// mamut shoot
if (m_fLastShootTime+4.0f<_pTimer->CurrentTick() &&
CanAttackEnemy(m_penEnemy, Cos(AngleDeg(50.0f)))) {
// stop moving (rotation and translation)
StopMoving();
autocall Fire() EReturn;
// rider (mamutman) shoot
} else if (m_bFrontRider || m_bMiddleRider || m_bRearRider) {
// stop rotating
StopRotating();
autocall RiderFire() EReturn;
}
} else {
// safety precocious from stack overflow loop
m_fShootTime = _pTimer->CurrentTick() + 0.25f;
}
return ETimer();
};
// close shoot
CloseShoot() : CEnemyBase::CloseShoot {
// shoot at enemy if possible
if (CalcDist(m_penEnemy)<m_fCloseDistance && CanHitEnemy(m_penEnemy, Cos(AngleDeg(130.0f)))) {
// set next shoot time
m_fShootTime = _pTimer->CurrentTick() + m_fCloseFireTime*(1.0f + FRnd()/3.0f);
// hit
// mamut shoot
if (m_fLastShootTime+4.0f<_pTimer->CurrentTick() &&
CanHitEnemy(m_penEnemy, Cos(AngleDeg(50.0f)))) {
// stop moving (rotaion and translation)
StopMoving();
autocall Hit() EReturn;
// rider (mamutman) shoot
} else if (m_bFrontRider || m_bMiddleRider || m_bRearRider) {
// stop rotating
StopRotating();
autocall RiderFire() EReturn;
}
// try attack shoot
} else {
jump AttackShoot();
}
return ETimer();
};
*/
Fire(EVoid) : CEnemyBase::Fire {
m_fLastShootTime = _pTimer->CurrentTick();
// fire projectile
StartModelAnim(MAMUT_ANIM_WOUND01, 0);
autowait(1.1f);
FireAirWave();
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(FRnd()*0.2f);
return EReturn();
};
Hit(EVoid) : CEnemyBase::Hit {
m_fLastShootTime = _pTimer->CurrentTick();
// hit the ground
StartModelAnim(MAMUT_ANIM_ATTACK01, 0);
autowait(0.3f);
if (CalcDist(m_penEnemy) < HIT_DISTANCE) {
FLOAT3D vSource = GetPlacement().pl_PositionVector +
FLOAT3D(en_mRotation(1, 2), en_mRotation(2, 2), en_mRotation(3, 2));
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
// damage
InflictRangeDamage(this, DMT_CLOSERANGE, 20.0f, vSource, 1.0f, 15.0f);
}
autowait(0.5f);
if (CalcDist(m_penEnemy) < HIT_DISTANCE) {
FLOAT3D vSource = GetPlacement().pl_PositionVector +
FLOAT3D(en_mRotation(1, 2), en_mRotation(2, 2), en_mRotation(3, 2));
PlaySound(m_soSound, SOUND_KICK, SOF_3D);
// damage
InflictRangeDamage(this, DMT_CLOSERANGE, 20.0f, vSource, 1.0f, 15.0f);
}
autowait(0.7f+FRnd()*0.1f);
return EReturn();
};
RiderFire() {
// if have any rider fire
if (m_bFrontRider || m_bMiddleRider || m_bRearRider) {
// prepare
PrepareBullet();
// find valid rider
INDEX iRider = IRnd()%3;
if (iRider==0 && !m_bFrontRider) { iRider = 1; }
if (iRider==1 && !m_bMiddleRider) { iRider = 2; }
if (iRider==2 && !m_bRearRider) { iRider = 0; }
if (iRider==0 && !m_bFrontRider) { iRider = 1; }
if (iRider==1 && !m_bMiddleRider) { iRider = 2; }
// animation
switch (iRider) {
case 0: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_FRONT, MAMUTMAN_ANIM_MOUNTEDATTACKFIRST, 0); break;
case 1: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_MIDDLE, MAMUTMAN_ANIM_MOUNTEDATTACKSECOND, 0); break;
case 2: PlayAttachmentAnim(MAMUT_ATTACHMENT_MAN_REAR, MAMUTMAN_ANIM_MOUNTEDATTACKTHIRD, 0); break;
}
// fire bullet
autowait(0.8f);
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
FireBullet();
}
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);
en_tmMaxHoldBreath = 35.0f;
en_fDensity = 4000.0f;
// set your appearance
GetModelObject()->StretchModel(FLOAT3D(2,2,2));
SetModel(MODEL_MAMUT);
ModelChangeNotify();
if (m_EmcChar==MAT_SUMMER) {
SetModelMainTexture(TEXTURE_MAMUT_SUMMER);
} else {
SetModelMainTexture(TEXTURE_MAMUT_WINTER);
}
SetHealth(700.0f);
m_fMaxHealth = 700.0f;
// set riders
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT);
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE);
RemoveAttachmentFromModel(*GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR);
if (m_bFrontRider) {
AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_FRONT,
MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0);
}
if (m_bMiddleRider) {
AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_MIDDLE,
MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0);
}
if (m_bRearRider) {
AddAttachmentToModel(this, *GetModelObject(), MAMUT_ATTACHMENT_MAN_REAR,
MODEL_MAMUTMAN, TEXTURE_MAMUTMAN, 0, 0, 0);
}
StandingAnim();
// setup moving speed
m_fWalkSpeed = FRnd() + 1.0f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f);
m_fAttackRunSpeed = FRnd() + 9.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*15.0f + 250.0f);
m_fCloseRunSpeed = FRnd() + 10.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*15.0f + 250.0f);
// setup attack distances
m_fAttackDistance = 120.0f;
m_fCloseDistance = 14.0f;
m_fStopDistance = 12.0f;
INDEX iTime = 4.0f;
if (m_bFrontRider) { iTime--; }
if (m_bMiddleRider) { iTime--; }
if (m_bRearRider) { iTime--; }
m_fAttackFireTime = iTime;
m_fCloseFireTime = 0.5f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 250.0f;
m_fBodyParts = 5;
m_fDamageWounded = 200.0f;
m_iScore = 5000;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,289 @@
326
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/MAMUTMAN/Mamutman.h"
%}
uses "Entities/EnemyBase";
uses "Entities/Bullet";
%{
// info structure
static EntityInfo eiMamutman = {
EIBT_FLESH, 60.0f,
0.0f, 2.0f, 0.0f,
0.0f, 1.5f, 0.0f,
};
#define FIRE FLOAT3D(0.0f, 0.8f, 0.0f)
#define FRONT 0
#define MIDDLE 1
#define REAR 2
%}
class CMamutman : CEnemyBase {
name "Mamutman";
thumbnail "Thumbnails\\Mamutman.tbn";
properties:
1 CEntityPointer m_penBullet, // bullet
2 BOOL m_bSpawned = FALSE,
3 INDEX m_bSpawnedPosition = 0,
components:
0 class CLASS_BASE "Classes\\EnemyBase.ecl",
1 class CLASS_BULLET "Classes\\Bullet.ecl",
5 model MODEL_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.mdl",
6 texture TEXTURE_MAMUTMAN "Models\\Enemies\\Mamutman\\Mamutman.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Mamutman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Mamutman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Mamutman\\Sounds\\Wound.wav",
53 sound SOUND_DEATH "Models\\Enemies\\Mamutman\\Sounds\\Death.wav",
54 sound SOUND_FIRE "Models\\Weapons\\Colt\\Sounds\\Fire.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return &eiMamutman;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// mamutman and mamut can't harm mamutman
if (!IsOfClass(penInflictor, "Mamutman") && !IsOfClass(penInflictor, "Mamut")) {
CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// death
INDEX AnimForDeath(void) {
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = MAMUTMAN_ANIM_DEATH01; break;
case 1: iAnim = MAMUTMAN_ANIM_DEATH01; break;
default: ASSERTALWAYS("Mamutman unknown death");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(MAMUTMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
StartModelAnim(MAMUTMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART);
};
void WalkingAnim(void) {
StartModelAnim(MAMUTMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void) {
StartModelAnim(MAMUTMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
StartModelAnim(MAMUTMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART);
};
// 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);
};
/************************************************************
* FIRE BULLET *
************************************************************/
void PrepareBullet(void) {
// bullet start position
CPlacement3D plBullet;
plBullet.pl_OrientationAngle = ANGLE3D(0,0,0);
plBullet.pl_PositionVector = FIRE;
plBullet.RelativeToAbsolute(GetPlacement());
// create bullet
m_penBullet = CreateEntity(plBullet, CLASS_BULLET);
// init bullet
EBulletInit eInit;
eInit.penOwner = this;
eInit.fDamage = 1.0f;
m_penBullet->Initialize(eInit);
((CBullet&)*m_penBullet).CalcTarget(m_penEnemy, 100);
};
// fire bullet
void FireBullet(void) {
((CBullet&)*m_penBullet).LaunchBullet(TRUE, TRUE, TRUE);
((CBullet&)*m_penBullet).DestroyBullet();
};
procedures:
/************************************************************
* CLASS INTERNAL *
************************************************************/
FallOnFloor(EVoid) {
// drop to floor
m_bSpawned = FALSE;
switch (m_bSpawnedPosition) {
case FRONT:
StartModelAnim(MAMUTMAN_ANIM_FALLFROMMAMUTFIRST, 0);
GiveImpulseTranslationRelative(FLOAT3D(FRnd()*4+8.0f, FRnd()+10.0f, FRnd()+2.0f));
break;
case MIDDLE:
StartModelAnim(MAMUTMAN_ANIM_FALLFROMMAMUTSECOND, 0);
GiveImpulseTranslationRelative(FLOAT3D(-FRnd()*4-8.0f, FRnd()+10.0f, FRnd()+2.0f));
break;
case REAR:
StartModelAnim(MAMUTMAN_ANIM_FALLFROMMAMUTTHIRD, 0);
GiveImpulseTranslationRelative(FLOAT3D(0.0f, FRnd()+10.0f, FRnd()*2+2.0f));
break;
}
// wait to touch brush or time limit
wait (10.0f) {
on (EBegin) : { resume; }
// brush touched
on (ETouch et) : {
if (et.penOther->GetRenderType()&RT_BRUSH) {
StopMoving();
stop;
}
resume;
}
// death
on (EDeath) : {
StopMoving();
SendEvent(EDeath());
jump CEnemyBase::MainLoop();
}
on (ETimer) : { stop; }
}
// get up
StopMoving();
StartModelAnim(MAMUTMAN_ANIM_GETUP01, 0);
wait (GetModelObject()->GetAnimLength(MAMUTMAN_ANIM_GETUP01)) {
on (EBegin) : { resume; }
on (ETimer) : { stop; }
// death
on (EDeath) : {
StopMoving();
SendEvent(EDeath());
jump CEnemyBase::MainLoop();
}
}
return EReturn();
};
/************************************************************
* PROCEDURES WHEN HARMED *
************************************************************/
// Play wound animation and falling body part
BeWounded(EDamage eDamage) : CEnemyBase::BeWounded
{
StopMoving();
// determine damage anim and play the wounding
if (IRnd()&1) {
StartModelAnim(MAMUTMAN_ANIM_FALL01, 0);
autowait(GetModelObject()->GetAnimLength(MAMUTMAN_ANIM_FALL01));
autowait(0.2f + FRnd()/3);
StartModelAnim(MAMUTMAN_ANIM_GETUP01, 0);
autowait(GetModelObject()->GetAnimLength(MAMUTMAN_ANIM_GETUP01));
} else if (TRUE) {
StartModelAnim(MAMUTMAN_ANIM_FALL02, 0);
autowait(GetModelObject()->GetAnimLength(MAMUTMAN_ANIM_FALL02));
autowait(0.2f + FRnd()/3);
StartModelAnim(MAMUTMAN_ANIM_GETUP02, 0);
autowait(GetModelObject()->GetAnimLength(MAMUTMAN_ANIM_GETUP02));
}
return EReturn();
};
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
Fire(EVoid) : CEnemyBase::Fire {
// wait for a while
StandingAnim();
PrepareBullet();
m_fLockOnEnemyTime = 0.2f + FRnd()/8;
autocall CEnemyBase::LockOnEnemy() EReturn;
// fire bullet
StartModelAnim(MAMUTMAN_ANIM_ATTACK02, 0);
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
FireBullet();
autowait(FRnd()/3 + 0.6f);
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);
SetHealth(40.0f);
m_fMaxHealth = 40.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 1000.0f;
// set your appearance
SetModel(MODEL_MAMUTMAN);
SetModelMainTexture(TEXTURE_MAMUTMAN);
if (!m_bSpawned) {
StandingAnim();
}
// setup moving speed
m_fWalkSpeed = FRnd() + 1.5f;
m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f);
m_fAttackRunSpeed = FRnd()*2.0f + 10.0f;
m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
m_fCloseRunSpeed = FRnd()*2.0f + 10.0f;
m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f);
// setup attack distances
m_fAttackDistance = 60.0f;
m_fCloseDistance = 0.0f;
m_fStopDistance = 17.0f;
m_fAttackFireTime = 1.0f;
m_fCloseFireTime = 1.0f;
m_fIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 20.0f;
m_fBodyParts = 4;
m_fDamageWounded = 30.0f;
m_iScore = 500;
// continue behavior in base class
jump CEnemyBase::MainLoop();
};
};

View File

@ -0,0 +1,197 @@
329
%{
#include "Entities/StdH/StdH.h"
#include "Models/Enemies/MANTAMAN/mantaman.h"
%}
uses "Entities/EnemyDive";
%{
static EntityInfo eiMantamanLiquid = {
EIBT_FLESH, 150.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
#define FIRE_WATER FLOAT3D(0.0f, 0.5f, -1.25f)
};
%}
class CMantaman : CEnemyDive {
name "Mantaman";
thumbnail "Thumbnails\\Mantaman.tbn";
properties:
1 BOOL m_FixedState "Fixed state" 'X' = FALSE, // fixed state on beginning
components:
0 class CLASS_BASE "Classes\\EnemyDive.ecl",
1 model MODEL_MANTAMAN "Models\\Enemies\\Mantaman\\Mantaman.mdl",
2 texture TEXTURE_MANTAMAN "Models\\Enemies\\Mantaman\\Mantaman.tex",
// ************** SOUNDS **************
50 sound SOUND_IDLE "Models\\Enemies\\Mantaman\\Sounds\\Idle.wav",
51 sound SOUND_SIGHT "Models\\Enemies\\Mantaman\\Sounds\\Sight.wav",
52 sound SOUND_WOUND "Models\\Enemies\\Mantaman\\Sounds\\Wound.wav",
53 sound SOUND_FIRE "Models\\Enemies\\Mantaman\\Sounds\\Fire.wav",
54 sound SOUND_KICK "Models\\Enemies\\Mantaman\\Sounds\\Kick.wav",
55 sound SOUND_DEATH "Models\\Enemies\\Mantaman\\Sounds\\Death.wav",
functions:
/* Entity info */
void *GetEntityInfo(void) {
return &eiMantamanLiquid;
};
/* Receive damage */
void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType,
FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection)
{
// mantaman can't harm mantaman
if (!IsOfClass(penInflictor, "Mantaman")) {
CEnemyDive::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);
}
};
// damage anim
INDEX AnimForDamage(FLOAT fDamage) {
INDEX iAnim;
switch (IRnd()%2) {
case 0: iAnim = MANTAMAN_ANIM_WOUND01; break;
case 1: iAnim = MANTAMAN_ANIM_WOUND02; break;
default: ASSERTALWAYS("Mantaman unknown liquid damage");
}
StartModelAnim(iAnim, 0);
return iAnim;
};
// death
INDEX AnimForDeath(void) {
StartModelAnim(MANTAMAN_ANIM_DEATH, 0);
return MANTAMAN_ANIM_DEATH;
};
void DeathNotify(void) {
ChangeCollisionBoxIndexWhenPossible(MANTAMAN_COLLISION_BOX_DEATH);
en_fDensity = 500.0f;
};
// virtual anim functions
void StandingAnim(void) {
if (m_FixedState) {
StartModelAnim(MANTAMAN_ANIM_DEFAULT_ANIMATION02, AOF_LOOPING|AOF_NORESTART);
} else {
StartModelAnim(MANTAMAN_ANIM_STANDORANDSWIMSLOW, AOF_LOOPING|AOF_NORESTART);
}
};
void WalkingAnim(void) {
StartModelAnim(MANTAMAN_ANIM_STANDORANDSWIMSLOW, AOF_LOOPING|AOF_NORESTART);
};
void RunningAnim(void) {
StartModelAnim(MANTAMAN_ANIM_SWIMFAST, AOF_LOOPING|AOF_NORESTART);
};
void RotatingAnim(void) {
StartModelAnim(MANTAMAN_ANIM_STANDORANDSWIMSLOW, AOF_LOOPING|AOF_NORESTART);
};
void ChangeCollisionToLiquid() {
ChangeCollisionBoxIndexWhenPossible(MANTAMAN_COLLISION_BOX_DEAFULT);
};
void ChangeCollisionToGround() {
ChangeCollisionBoxIndexWhenPossible(MANTAMAN_COLLISION_BOX_DEAFULT);
};
// 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);
};
procedures:
/************************************************************
* A T T A C K E N E M Y *
************************************************************/
AttackEnemy(EVoid) : CEnemyBase::AttackEnemy {
if (m_FixedState) {
m_FixedState = FALSE;
StartModelAnim(MANTAMAN_ANIM_MORPH, 0);
wait(GetModelObject()->GetAnimLength(MANTAMAN_ANIM_MORPH)) {
on (EBegin) : { resume; }
on (ETimer) : { stop; }
on (EWatch) : { resume; }
on (EDamage) : { resume; }
}
}
jump CEnemyBase::AttackEnemy();
};
DiveFire(EVoid) : CEnemyDive::DiveFire {
// fire projectile
StartModelAnim(MANTAMAN_ANIM_ATTACK01, 0);
autowait(0.3f);
ShootProjectile(PRT_MANTAMAN_FIRE, FIRE_WATER, ANGLE3D(0, 0, 0));
PlaySound(m_soSound, SOUND_FIRE, SOF_3D);
autowait(0.8f);
StandingAnim();
autowait(FRnd()/2 + _pTimer->TickQuantum);
return EReturn();
};
/************************************************************
* M A I N *
************************************************************/
Main(EVoid) {
// declare yourself as a model
InitAsModel();
SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASGILLS);
SetCollisionFlags(ECF_MODEL);
SetFlags(GetFlags()|ENF_ALIVE);
SetHealth(50.0f);
m_fMaxHealth = 50.0f;
en_tmMaxHoldBreath = 5.0f;
en_fDensity = 1000.0f;
// set your appearance
SetModel(MODEL_MANTAMAN);
SetModelMainTexture(TEXTURE_MANTAMAN);
// dive moving properties
m_fDiveWalkSpeed = FRnd() + 2.0f;
m_aDiveWalkRotateSpeed = FRnd()*10.0f + 500.0f;
m_fDiveAttackRunSpeed = FRnd()*4.0f + 14.0f;
m_aDiveAttackRotateSpeed = FRnd()*25 + 250.0f;
m_fDiveCloseRunSpeed = FRnd()*2.0f + 6.5f;
m_aDiveCloseRotateSpeed = FRnd()*50 + 250.0f;
// attack properties
m_fDiveAttackDistance = 100.0f;
m_fDiveCloseDistance = 0.0f;
m_fDiveStopDistance = 5.0f;
m_fDiveAttackFireTime = 3.0f;
m_fDiveCloseFireTime = 2.0f;
m_fDiveIgnoreRange = 200.0f;
// damage/explode properties
m_fBlowUpAmount = 140.0f;
m_fBodyParts = 4;
m_fDamageWounded = 30.0f;
m_iScore = 2000;
// allowed types
m_EedtType = EDT_DIVE_ONLY;
// continue behavior in base class
jump CEnemyDive::MainLoop();
};
};

View File

@ -0,0 +1,59 @@
202
%{
#include "Entities/StdH/StdH.h"
%}
class CMarker: CEntity {
name "Marker";
thumbnail "Thumbnails\\Marker.tbn";
features "HasName", "HasTarget", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "Marker",
3 CTString m_strDescription = "",
2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_dGREEN|0xFF),
components:
1 model MODEL_MARKER "Models\\Editor\\Axis.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex"
functions:
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("-><none>");
if (m_penTarget!=NULL) {
((CTString&)m_strDescription).PrintF("->%s", (const char*)m_penTarget->GetName());
}
return m_strDescription;
}
/* Check if entity is moved on a route set up by its targets. */
BOOL MovesByTargetedRoute(CTString &strTargetProperty) const {
strTargetProperty = "Target";
return TRUE;
};
/* Check if entity can drop marker for making linked route. */
BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const {
fnmMarkerClass = CTFILENAME("Classes\\Marker.ecl");
strTargetProperty = "Target";
return TRUE;
}
// this is MARKER !!!!
virtual BOOL IsMarker(void) const {
return TRUE;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
return;
}
};

View File

@ -0,0 +1,63 @@
226
%{
#include "Entities/StdH/StdH.h"
extern INDEX ent_bReportBrokenChains;
%}
class CMessageHolder : CRationalEntity {
name "MessageHolder";
thumbnail "Thumbnails\\MessageHolder.tbn";
features "HasName", "IsTargetable";
properties:
1 CTString m_strName "Name" 'N' = "MessageHolder",
3 CTString m_strDescription = "",
2 CTFileName m_fnmMessage "Message" 'M' = CTString(""),
4 FLOAT m_fDistance "Distance" 'D' = 2.0f,
5 BOOL m_bActive "Active" 'A' = TRUE,
6 CEntityPointer m_penNext "Next" 'X',
components:
1 model MODEL_MARKER "Models\\Editor\\MessageHolder.mdl",
2 texture TEXTURE_MARKER "Models\\Editor\\MessageHolder.tex"
functions:
const CTString &GetDescription(void) const {
((CTString&)m_strDescription).PrintF("%s", (const char*)m_fnmMessage.FileName());
return m_strDescription;
}
procedures:
Main()
{
InitAsEditorModel();
SetPhysicsFlags(EPF_MODEL_IMMATERIAL);
SetCollisionFlags(ECF_IMMATERIAL);
// set appearance
SetModel(MODEL_MARKER);
SetModelMainTexture(TEXTURE_MARKER);
wait() {
on (ETrigger eTrigger): {
if (!m_bActive) {
resume;
}
CEntity *penCaused = FixupCausedToPlayer(this, eTrigger.penCaused);
EComputerMessage eMsg;
eMsg.fnmMessage = m_fnmMessage;
penCaused->SendEvent(eMsg);
resume;
}
on (EActivate): {
m_bActive = TRUE;
resume;
}
on (EDeactivate): {
m_bActive = FALSE;
resume;
}
}
return;
}
};

View File

@ -0,0 +1,102 @@
807
%{
#include "Entities/StdH/StdH.h"
#include "Models/Items/ItemHolder/ItemHolder.h"
%}
uses "Entities/Item";
// event for sending through receive item
event EMessageItem {
CTFileName fnmMessage,
};
%{
%}
class CMessageItem : CItem {
name "MessageItem";
thumbnail "Thumbnails\\MessageItem.tbn";
properties:
1 CTString m_strName "Name" 'N' = "MessageItem",
2 CTString m_strDescription = "",
3 CTFileName m_fnmMessage "Message" 'M' = CTString(""),
4 INDEX m_iSoundComponent = 0,
components:
0 class CLASS_BASE "Classes\\Item.ecl",
1 model MODEL_PERGAMENT "Models\\Items\\Pergament\\Pergament.mdl",
2 texture TEXTURE_PERGAMENT "Models\\Items\\Pergament\\Pergament.tex",
// ********* MISC *********
255 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex",
256 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl",
// ************** SOUNDS **************
301 sound SOUND_KEY "Sounds\\Items\\Key.wav",
functions:
void Precache(void) {
PrecacheSound(SOUND_KEY);
}
/* Fill in entity statistics - for AI purposes only */
BOOL FillEntityStatistics(EntityStats *pes)
{
pes->es_strName = "Pergament";
pes->es_ctCount = 1;
pes->es_ctAmmount = 1;
pes->es_fValue = 1;
pes->es_iScore = 0;//m_iScore;
return TRUE;
}
// render particles
void RenderParticles(void) {
// no particles when not existing
if (GetRenderType()!=CEntity::RT_MODEL) {
return;
}
Particles_Stardust(this, 0.9f, 0.70f, PT_STAR08, 32);
}
// set health properties depending on type
void SetProperties(void) {
m_fRespawnTime = 10.0f;
m_strDescription = m_fnmMessage.FileName();
// set appearance
AddItem(MODEL_PERGAMENT, TEXTURE_PERGAMENT, 0, 0, 0);
// add flare
AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) );
StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f));
m_iSoundComponent = SOUND_KEY;
};
procedures:
ItemCollected(EPass epass) : CItem::ItemCollected {
ASSERT(epass.penOther!=NULL);
// send key to entity
EMessageItem eMessage;
eMessage.fnmMessage = m_fnmMessage;
// if health is received
if (epass.penOther->ReceiveItem(eMessage)) {
// play the pickup sound
m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f);
PlaySound(m_soPick, m_iSoundComponent, SOF_3D);
m_fPickSoundLen = GetSoundLength(m_iSoundComponent);
jump CItem::ItemReceived();
}
return;
};
Main() {
Initialize(); // initialize base class
StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART);
ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL);
SetProperties(); // set properties
jump CItem::ItemLoop();
};
};

Some files were not shown because too many files have changed in this diff Show More