mirror of
https://github.com/ptitSeb/Serious-Engine
synced 2024-12-26 15:44:51 +01:00
Merge pull request #14 from ptitSeb/master
Preliminary support for The First Encounter
This commit is contained in:
commit
56de02e4b8
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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
6
Sources/Engine/Base/CTString.cpp
Normal file → Executable 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
2
Sources/Engine/Base/ProgressHook.cpp
Normal file → Executable 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
3
Sources/Engine/Base/SDL/SDLInput.cpp
Normal file → Executable 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
29
Sources/Engine/Light/LayerMixer.cpp
Normal file → Executable 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
4
Sources/Engine/Math/Functions.h
Normal file → Executable 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
24
Sources/Engine/Math/Quaternion.h
Normal file → Executable 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
2
Sources/Engine/Math/Vector.h
Normal file → Executable 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
4
Sources/Engine/Sound/SoundObject.h
Normal file → Executable 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
70
Sources/Entities/Acid.es
Normal 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
151
Sources/Entities/AirWave.es
Normal 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;
|
||||
}
|
||||
};
|
391
Sources/Entities/AmmoItem.es
Normal file
391
Sources/Entities/AmmoItem.es
Normal 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();
|
||||
};
|
||||
};
|
203
Sources/Entities/AmmoPack.es
Normal file
203
Sources/Entities/AmmoPack.es
Normal 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();
|
||||
};
|
||||
};
|
146
Sources/Entities/AnimationChanger.es
Normal file
146
Sources/Entities/AnimationChanger.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
147
Sources/Entities/AnimationHub.es
Normal file
147
Sources/Entities/AnimationHub.es
Normal 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();
|
||||
}
|
||||
};
|
||||
|
254
Sources/Entities/ArmorItem.es
Normal file
254
Sources/Entities/ArmorItem.es
Normal 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();
|
||||
};
|
||||
};
|
68
Sources/Entities/BackgroundViewer.es
Normal file
68
Sources/Entities/BackgroundViewer.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
1238
Sources/Entities/BasicEffects.es
Normal file
1238
Sources/Entities/BasicEffects.es
Normal file
File diff suppressed because it is too large
Load Diff
450
Sources/Entities/Beast.es
Normal file
450
Sources/Entities/Beast.es
Normal 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
209
Sources/Entities/BigHead.es
Normal 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();
|
||||
};
|
||||
};
|
126
Sources/Entities/BlendController.es
Normal file
126
Sources/Entities/BlendController.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
130
Sources/Entities/BloodSpray.es
Normal file
130
Sources/Entities/BloodSpray.es
Normal 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
385
Sources/Entities/Boneman.es
Normal 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();
|
||||
};
|
||||
};
|
65
Sources/Entities/Bouncer.es
Normal file
65
Sources/Entities/Bouncer.es
Normal 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
420
Sources/Entities/Bullet.es
Normal 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
443
Sources/Entities/Camera.es
Normal 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;
|
||||
};
|
||||
};
|
||||
|
69
Sources/Entities/CameraMarker.es
Normal file
69
Sources/Entities/CameraMarker.es
Normal 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;
|
||||
}
|
||||
|
||||
};
|
||||
|
604
Sources/Entities/CannonBall.es
Normal file
604
Sources/Entities/CannonBall.es
Normal 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
182
Sources/Entities/Catman.es
Normal 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();
|
||||
};
|
||||
};
|
1117
Sources/Entities/Common/Common.cpp
Normal file
1117
Sources/Entities/Common/Common.cpp
Normal file
File diff suppressed because it is too large
Load Diff
215
Sources/Entities/Common/Common.h
Normal file
215
Sources/Entities/Common/Common.h
Normal 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);
|
0
Sources/Entities/Common/Debris.cpp
Normal file
0
Sources/Entities/Common/Debris.cpp
Normal file
157
Sources/Entities/Common/Flags.h
Normal file
157
Sources/Entities/Common/Flags.h
Normal 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. */
|
||||
|
65
Sources/Entities/Common/GameInterface.h
Normal file
65
Sources/Entities/Common/GameInterface.h
Normal 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. */
|
||||
|
1106
Sources/Entities/Common/HUD.cpp
Normal file
1106
Sources/Entities/Common/HUD.cpp
Normal file
File diff suppressed because it is too large
Load Diff
0
Sources/Entities/Common/HUD.h
Normal file
0
Sources/Entities/Common/HUD.h
Normal file
2988
Sources/Entities/Common/Particles.cpp
Normal file
2988
Sources/Entities/Common/Particles.cpp
Normal file
File diff suppressed because it is too large
Load Diff
88
Sources/Entities/Common/Particles.h
Normal file
88
Sources/Entities/Common/Particles.h
Normal 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);
|
280
Sources/Entities/Common/PathFinding.cpp
Normal file
280
Sources/Entities/Common/PathFinding.cpp
Normal 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);
|
||||
}
|
40
Sources/Entities/Common/PathFinding.h
Normal file
40
Sources/Entities/Common/PathFinding.h
Normal 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. */
|
||||
|
0
Sources/Entities/Common/Stats.cpp
Normal file
0
Sources/Entities/Common/Stats.cpp
Normal file
373
Sources/Entities/Common/WeaponPositions.h
Normal file
373
Sources/Entities/Common/WeaponPositions.h
Normal 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
|
||||
|
94
Sources/Entities/Copier.es
Normal file
94
Sources/Entities/Copier.es
Normal 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
124
Sources/Entities/Counter.es
Normal 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;
|
||||
}
|
||||
};
|
214
Sources/Entities/CrateRider.es
Normal file
214
Sources/Entities/CrateRider.es
Normal 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
743
Sources/Entities/Cyborg.es
Normal 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();
|
||||
};
|
||||
};
|
132
Sources/Entities/CyborgBike.es
Normal file
132
Sources/Entities/CyborgBike.es
Normal 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;
|
||||
};
|
||||
};
|
73
Sources/Entities/Damager.es
Normal file
73
Sources/Entities/Damager.es
Normal 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
276
Sources/Entities/Debris.es
Normal 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;
|
||||
}
|
||||
};
|
415
Sources/Entities/DestroyableArchitecture.es
Normal file
415
Sources/Entities/DestroyableArchitecture.es
Normal 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
2415
Sources/Entities/Devil.es
Normal file
File diff suppressed because it is too large
Load Diff
155
Sources/Entities/DevilMarker.es
Normal file
155
Sources/Entities/DevilMarker.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
270
Sources/Entities/DevilProjectile.es
Normal file
270
Sources/Entities/DevilProjectile.es
Normal 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;
|
||||
}
|
||||
};
|
334
Sources/Entities/DoorController.es
Normal file
334
Sources/Entities/DoorController.es
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
616
Sources/Entities/Dragonman.es
Normal file
616
Sources/Entities/Dragonman.es
Normal 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();
|
||||
};
|
||||
};
|
291
Sources/Entities/EffectMarker.es
Normal file
291
Sources/Entities/EffectMarker.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
468
Sources/Entities/Effector.es
Normal file
468
Sources/Entities/Effector.es
Normal 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;
|
||||
}
|
||||
};
|
1503
Sources/Entities/Elemental.es
Normal file
1503
Sources/Entities/Elemental.es
Normal file
File diff suppressed because it is too large
Load Diff
2785
Sources/Entities/EnemyBase.es
Normal file
2785
Sources/Entities/EnemyBase.es
Normal file
File diff suppressed because it is too large
Load Diff
105
Sources/Entities/EnemyCounter.es
Normal file
105
Sources/Entities/EnemyCounter.es
Normal 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;
|
||||
}
|
||||
};
|
250
Sources/Entities/EnemyDive.es
Normal file
250
Sources/Entities/EnemyDive.es
Normal 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();
|
||||
}
|
||||
};
|
479
Sources/Entities/EnemyFly.es
Normal file
479
Sources/Entities/EnemyFly.es
Normal 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();
|
||||
}
|
||||
};
|
53
Sources/Entities/EnemyMarker.es
Normal file
53
Sources/Entities/EnemyMarker.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
283
Sources/Entities/EnemyRunInto.es
Normal file
283
Sources/Entities/EnemyRunInto.es
Normal 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;
|
||||
};
|
||||
};
|
389
Sources/Entities/EnemySpawner.es
Normal file
389
Sources/Entities/EnemySpawner.es
Normal 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;
|
||||
};
|
||||
};
|
5430
Sources/Entities/Entities.dsp
Normal file
5430
Sources/Entities/Entities.dsp
Normal file
File diff suppressed because it is too large
Load Diff
416
Sources/Entities/EnvironmentBase.es
Normal file
416
Sources/Entities/EnvironmentBase.es
Normal 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();
|
||||
};
|
||||
};
|
92
Sources/Entities/EnvironmentMarker.es
Normal file
92
Sources/Entities/EnvironmentMarker.es
Normal 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
264
Sources/Entities/Eruptor.es
Normal 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
517
Sources/Entities/Eyeman.es
Normal 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
335
Sources/Entities/Fish.es
Normal 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
350
Sources/Entities/Fishman.es
Normal 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
182
Sources/Entities/Flame.es
Normal 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;
|
||||
}
|
||||
};
|
142
Sources/Entities/FogMarker.es
Normal file
142
Sources/Entities/FogMarker.es
Normal 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;
|
||||
}
|
||||
};
|
272
Sources/Entities/GhostBusterRay.cpp
Normal file
272
Sources/Entities/GhostBusterRay.cpp
Normal 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;};
|
229
Sources/Entities/GhostBusterRay.es
Normal file
229
Sources/Entities/GhostBusterRay.es
Normal 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;
|
||||
}
|
||||
};
|
73
Sources/Entities/GhostBusterRay.h
Normal file
73
Sources/Entities/GhostBusterRay.h
Normal 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
|
49
Sources/Entities/GhostBusterRay_tables.h
Normal file
49
Sources/Entities/GhostBusterRay_tables.h
Normal 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
341
Sources/Entities/Gizmo.es
Normal 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
155
Sources/Entities/Global.es
Normal 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");
|
||||
}
|
||||
};
|
93
Sources/Entities/GradientMarker.es
Normal file
93
Sources/Entities/GradientMarker.es
Normal 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;
|
||||
}
|
||||
};
|
162
Sources/Entities/GravityMarker.es
Normal file
162
Sources/Entities/GravityMarker.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
83
Sources/Entities/GravityRouter.es
Normal file
83
Sources/Entities/GravityRouter.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
126
Sources/Entities/HazeMarker.es
Normal file
126
Sources/Entities/HazeMarker.es
Normal 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
691
Sources/Entities/Headman.es
Normal 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();
|
||||
};
|
||||
};
|
263
Sources/Entities/HealthItem.es
Normal file
263
Sources/Entities/HealthItem.es
Normal 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
180
Sources/Entities/Huanman.es
Normal 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
279
Sources/Entities/Item.es
Normal 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
350
Sources/Entities/KeyItem.es
Normal 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();
|
||||
};
|
||||
};
|
5
Sources/Entities/LastFileID.txt
Normal file
5
Sources/Entities/LastFileID.txt
Normal 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
454
Sources/Entities/Light.es
Normal 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;
|
||||
};
|
||||
};
|
33
Sources/Entities/LightStyle.es
Normal file
33
Sources/Entities/LightStyle.es
Normal 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;
|
||||
}
|
||||
};
|
258
Sources/Entities/Lightning.es
Normal file
258
Sources/Entities/Lightning.es
Normal 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
452
Sources/Entities/Mamut.es
Normal 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();
|
||||
};
|
||||
};
|
289
Sources/Entities/Mamutman.es
Normal file
289
Sources/Entities/Mamutman.es
Normal 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();
|
||||
};
|
||||
};
|
197
Sources/Entities/Mantaman.es
Normal file
197
Sources/Entities/Mantaman.es
Normal 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();
|
||||
};
|
||||
};
|
59
Sources/Entities/Marker.es
Normal file
59
Sources/Entities/Marker.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
63
Sources/Entities/MessageHolder.es
Normal file
63
Sources/Entities/MessageHolder.es
Normal 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;
|
||||
}
|
||||
};
|
||||
|
102
Sources/Entities/MessageItem.es
Normal file
102
Sources/Entities/MessageItem.es
Normal 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
Loading…
Reference in New Issue
Block a user