diff --git a/source/glest_game/game/game_camera.cpp b/source/glest_game/game/game_camera.cpp index 6e8bd8c6..0a418323 100644 --- a/source/glest_game/game/game_camera.cpp +++ b/source/glest_game/game/game_camera.cpp @@ -19,6 +19,7 @@ #include "conversion.h" #include "platform_common.h" #include "leak_dumper.h" +#include "randomgen.h" using namespace Shared::Graphics; @@ -41,6 +42,7 @@ const float GameCamera::vTransitionMult= 0.125f; const float GameCamera::hTransitionMult= 0.125f; const float GameCamera::defaultHeight= 20.f; const float GameCamera::centerOffsetZ= 8.0f; +const float GameCamera::shakeDist= 50.f; // ================= Constructor ================= @@ -69,6 +71,9 @@ GameCamera::GameCamera() : pos(0.f, defaultHeight, 0.f), move= Vec3f(0.f); + shakeDecrement=0.f; + currentShakeIntensity=0; + //maxRenderDistance = Config::getInstance().getFloat("RenderDistanceMax","64"); maxHeight = Config::getInstance().getFloat("CameraMaxDistance","20"); minHeight = Config::getInstance().getFloat("CameraMinDistance","7"); @@ -133,8 +138,48 @@ void GameCamera::setPos(Vec3f pos){ destPos.z = pos.z; } -void GameCamera::update(){ +void GameCamera::shake(int shakeDuration, int shakeStartIntensity , bool cameraDistanceAffected, Vec3f unitVector) { + float currentDurationLeft=0; + float incomingShakeIntensity=((float) shakeStartIntensity)/1000; + // calculate the shake duration which is left + if(this->currentShakeIntensity > 0.f && this->shakeDecrement != 0.f){ + currentDurationLeft=this->currentShakeIntensity / this->shakeDecrement; + } + + // reduce new shake effect camera distance related + if (cameraDistanceAffected) { + incomingShakeIntensity=incomingShakeIntensity*(1.f-unitVector.dist(getPos())/GameCamera::shakeDist); + } + + // add camera shake effect to current one ( if exsists ). + if(this->currentShakeIntensity>0){ + this->currentShakeIntensity = this->currentShakeIntensity+incomingShakeIntensity ; + } + else { + this->currentShakeIntensity = incomingShakeIntensity ; + } + + // use bigger shakeDuration to calculate new shakeDecrement + if(currentDurationLeft < shakeDuration){ + this->shakeDecrement = currentShakeIntensity / ((float) shakeDuration); + } + else if(currentDurationLeft!=0.0f) + { + this->shakeDecrement = currentShakeIntensity / ((float) currentDurationLeft); + } +} + +void GameCamera::shakeCamera(){ + //RandomGen random; + if(currentShakeIntensity > 0.f) { + pos.x += (((float) (rand() % 50)) / 50.f - 0.5f) * currentShakeIntensity; + pos.z += (((float) (rand() % 50)) / 50.f - 0.5f) * currentShakeIntensity; + currentShakeIntensity -= shakeDecrement; + } +} + +void GameCamera::update(){ //move XZ if(move.z){ moveForwardH(speed * move.z, 0.9f); @@ -186,8 +231,8 @@ void GameCamera::update(){ if(abs(destPos.z - pos.z) > 0.01f) { pos.z += (destPos.z - pos.z) / 32.0f; } - clampAng(); + shakeCamera(); if(clampDisable == false && clampBounds){ clampPosXYZ(0.0f, (float)limitX, minHeight, maxHeight, 0.0f, (float)limitY); diff --git a/source/glest_game/game/game_camera.h b/source/glest_game/game/game_camera.h index 70ae23c8..d6d0312d 100644 --- a/source/glest_game/game/game_camera.h +++ b/source/glest_game/game/game_camera.h @@ -50,6 +50,7 @@ public: static const float hTransitionMult; static const float defaultHeight; static const float centerOffsetZ; + static const float shakeDist; public: enum State{ @@ -72,6 +73,8 @@ private: Vec3f move; + float shakeDecrement; + float currentShakeIntensity; State state; int limitX; @@ -115,6 +118,8 @@ public: void setPos(Vec2f pos); void setPos(Vec3f pos); + void shake(int shakeDuration, int shakeStartIntensity , bool cameraDistanceAffected, Vec3f unitVector); + void setMoveX(float f) {this->move.x= f;} void setMoveY(float f) {this->move.y= f;} void setMoveZ(float f) {this->move.z= f;} @@ -177,7 +182,7 @@ private: void clampAng(); void moveUp(float dist); void rotateHV(float h, float v); - + void shakeCamera(); }; }} //end namespace diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index be42324a..7a72c5ce 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -528,6 +528,54 @@ void SkillType::load(const XmlNode *sn, const XmlNode *attackBoostsNode, const XmlNode *attackBoostNode = sn->getChild("attack-boost"); loadAttackBoost(attackBoostsNode, attackBoostNode, ft, parentLoader, dir, currentPath, loadedFileList, tt); } + + shake=false; + shakeIntensity=50; + shakeDuration=300; + shakeStartTime=0.0f; + shakeSelfEnabled=false; + shakeSelfVisible=true; + shakeSelfInCameraView=false; + shakeSelfCameraAffected=false; + shakeTeamEnabled=false; + shakeTeamVisible=true; + shakeTeamInCameraView=false; + shakeTeamCameraAffected=false; + shakeEnemyEnabled=false; + shakeEnemyVisible=true; + shakeEnemyInCameraView=false; + shakeEnemyCameraAffected=false; + + if (sn->hasChild("shake")) { + XmlNode *shakeNode=sn->getChild("shake"); + shake= shakeNode->getAttribute("enabled")->getBoolValue(); + shakeIntensity= shakeNode->getAttribute("intensity")->getIntValue(); + shakeDuration= shakeNode->getAttribute("duration")->getIntValue(); + if (shakeNode->hasAttribute("start-time")) { + shakeStartTime= shakeNode->getAttribute("start-time")->getFloatValue(); + } + if (shakeNode->hasChild("self")) { + shakeSelfEnabled= shakeNode->getChild("enemy")->getAttribute("enabled")->getBoolValue(); + shakeSelfVisible= shakeNode->getChild("self")->getAttribute("visible")->getBoolValue(); + shakeSelfInCameraView= shakeNode->getChild("self")->getAttribute("in-camera-view")->getBoolValue(); + shakeSelfCameraAffected= shakeNode->getChild("self")->getAttribute("camera-distance-affected")->getBoolValue(); + } + if (shakeNode->hasChild("team")) { + shakeTeamEnabled= shakeNode->getChild("enemy")->getAttribute("enabled")->getBoolValue(); + shakeTeamVisible= shakeNode->getChild("team")->getAttribute("visible")->getBoolValue(); + shakeTeamInCameraView= shakeNode->getChild("team")->getAttribute("in-camera-view")->getBoolValue(); + shakeTeamCameraAffected= shakeNode->getChild("team")->getAttribute("camera-distance-affected")->getBoolValue(); + } + if (shakeNode->hasChild("enemy")) { + shakeEnemyEnabled= shakeNode->getChild("enemy")->getAttribute("enabled")->getBoolValue(); + shakeEnemyVisible= shakeNode->getChild("enemy")->getAttribute("visible")->getBoolValue(); + shakeEnemyInCameraView= shakeNode->getChild("enemy")->getAttribute("in-camera-view")->getBoolValue(); + shakeEnemyCameraAffected= shakeNode->getChild("enemy")->getAttribute("camera-distance-affected")->getBoolValue(); + } + + //visible-for (team, self,all, team-and-visible, self-and-visible, all-and-visible ) + + } } bool SkillType::CanCycleNextRandomAnimation(const int *animationRandomCycleCount) const { diff --git a/source/glest_game/types/skill_type.h b/source/glest_game/types/skill_type.h index 15e8369b..75db79b7 100644 --- a/source/glest_game/types/skill_type.h +++ b/source/glest_game/types/skill_type.h @@ -133,6 +133,24 @@ protected: int speed; int animSpeed; + bool shake; + int shakeIntensity; + int shakeDuration; + float shakeStartTime; + bool shakeSelfEnabled; + bool shakeSelfVisible; + bool shakeSelfInCameraView; + bool shakeSelfCameraAffected; + bool shakeTeamEnabled; + bool shakeTeamVisible; + bool shakeTeamInCameraView; + bool shakeTeamCameraAffected; + bool shakeEnemyEnabled; + bool shakeEnemyVisible; + bool shakeEnemyInCameraView; + bool shakeEnemyCameraAffected; + + int animationRandomCycleMaxcount; vector animations; vector animationAttributes; @@ -179,6 +197,25 @@ public: Model *getAnimation(float animProgress=0, const Unit *unit=NULL, int *lastAnimationIndex=NULL, int *animationRandomCycleCount=NULL) const; StaticSound *getSound() const {return sounds.getRandSound();} float getSoundStartTime() const {return soundStartTime;} + + float getShakeStartTime() const {return shakeStartTime;} + bool getShake() const {return shake;} + int getShakeIntensity() const {return shakeIntensity;} + int getShakeDuration() const {return shakeDuration;} + + bool getShakeSelfEnabled() const {return shakeSelfEnabled;} + bool getShakeSelfVisible() const {return shakeSelfVisible;} + bool getShakeSelfInCameraView() const {return shakeSelfInCameraView;} + bool getShakeSelfCameraAffected() const {return shakeSelfCameraAffected;} + bool getShakeTeamEnabled() const {return shakeTeamEnabled;} + bool getShakeTeamVisible() const {return shakeTeamVisible;} + bool getShakeTeamInCameraView() const {return shakeTeamInCameraView;} + bool getShakeTeamCameraAffected() const {return shakeTeamCameraAffected;} + bool getShakeEnemyEnabled() const {return shakeEnemyEnabled;} + bool getShakeEnemyVisible() const {return shakeEnemyVisible;} + bool getShakeEnemyInCameraView() const {return shakeEnemyInCameraView;} + bool getShakeEnemyCameraAffected() const {return shakeEnemyCameraAffected;} + bool isAttackBoostEnabled() const { return attackBoost.enabled; } const AttackBoost * getAttackBoost() const { return &attackBoost; } diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 31423a67..de9d6560 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -137,6 +137,42 @@ bool UnitUpdater::updateUnit(Unit *unit) { } } + if (currSkill->getShake()) { + float shakeStartTime = currSkill->getShakeStartTime(); + if (shakeStartTime >= unit->getLastAnimProgressAsFloat() + && shakeStartTime < unit->getAnimProgressAsFloat()) { + bool visibleAffected=false; + bool cameraViewAffected=false; + bool cameraDistanceAffected=false; + bool enabled=false; + if (game->getWorld()->getThisFactionIndex() == unit->getFactionIndex()) { + visibleAffected=currSkill->getShakeSelfVisible(); + cameraViewAffected=currSkill->getShakeSelfInCameraView(); + cameraDistanceAffected=currSkill->getShakeSelfCameraAffected(); + enabled=currSkill->getShakeSelfEnabled(); + } else if (unit->getTeam() == world->getThisTeamIndex()) { + visibleAffected=currSkill->getShakeTeamVisible(); + cameraViewAffected=currSkill->getShakeTeamInCameraView(); + cameraDistanceAffected=currSkill->getShakeTeamCameraAffected(); + enabled=currSkill->getShakeTeamEnabled(); + } else { + visibleAffected=currSkill->getShakeEnemyVisible(); + cameraViewAffected=currSkill->getShakeEnemyInCameraView(); + cameraDistanceAffected=currSkill->getShakeEnemyCameraAffected(); + enabled=currSkill->getShakeEnemyEnabled(); + } + + bool visibility=(!visibleAffected)||(map->getSurfaceCell(Map::toSurfCoords(unit->getPos()))->isVisible(world->getThisTeamIndex()) || + (game->getWorld()->showWorldForPlayer(game->getWorld()->getThisTeamIndex()) == true)); + + bool cameraAffected=(!cameraViewAffected) || unit->getVisible(); + + if(visibility && cameraAffected && enabled) { + game->getGameCameraPtr()->shake( currSkill->getShakeDuration(), currSkill->getShakeIntensity(),cameraDistanceAffected,unit->getCurrVector()); + } + } + } + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after playsound]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); unit->updateTimedParticles();