00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <actions/TankFalling.h>
00022 #include <actions/TankDamage.h>
00023 #include <target/TargetContainer.h>
00024 #include <target/TargetState.h>
00025 #include <target/TargetParachute.h>
00026 #include <target/TargetDamageCalc.h>
00027 #include <target/TargetLife.h>
00028 #include <target/TargetSpace.h>
00029 #include <tank/Tank.h>
00030 #include <tank/TankAccessories.h>
00031 #include <engine/ScorchedContext.h>
00032 #include <engine/ActionController.h>
00033 #include <weapons/AccessoryStore.h>
00034 #include <weapons/Parachute.h>
00035 #include <common/OptionsScorched.h>
00036 #include <landscapemap/DeformLandscape.h>
00037 #ifndef S3D_SERVER
00038 #include <land/VisibilityPatchGrid.h>
00039 #endif
00040
00041 TankFalling::TankFalling(Weapon *weapon, unsigned int fallingPlayerId,
00042 WeaponFireContext &weaponContext,
00043 Parachute *parachute) :
00044 weapon_(weapon),
00045 fallingPlayerId_(fallingPlayerId),
00046 weaponContext_(weaponContext), parachute_(parachute)
00047 {
00048 }
00049
00050 TankFalling::~TankFalling()
00051 {
00052 if (context_)
00053 {
00054 Target *target = context_->getTargetContainer().getTargetById(fallingPlayerId_);
00055 if (target)
00056 {
00057 if (target->getTargetState().getFalling() == this)
00058 {
00059 target->getTargetState().setFalling(0);
00060 }
00061 }
00062 }
00063 }
00064
00065 void TankFalling::init()
00066 {
00067 Target *current =
00068 context_->getTargetContainer().getTargetById(fallingPlayerId_);
00069 if (current &&
00070 !current->getTargetState().getFalling() &&
00071 !current->getTargetState().getNoFalling())
00072 {
00073 current->getTargetState().setFalling(this);
00074
00075
00076 tankStartPosition_ = current->getLife().getTargetPosition();
00077
00078 FixedVector velocity(0, 0, 0);
00079 PhysicsParticleInfo info(ParticleTypeFalling, fallingPlayerId_, this);
00080 setPhysics(info, tankStartPosition_, velocity,
00081 0, 0, 0, false);
00082 }
00083 else
00084 {
00085 collision_ = true;
00086 }
00087 }
00088
00089 std::string TankFalling::getActionDetails()
00090 {
00091 return S3D::formatStringBuffer("%u %s",
00092 fallingPlayerId_, weapon_->getParent()->getName());
00093 }
00094
00095 void TankFalling::simulate(fixed frameTime, bool &remove)
00096 {
00097 if (!collision_)
00098 {
00099
00100 if (parachute_) applyForce(parachute_->getSlowForce());
00101
00102
00103 Target *target = context_->getTargetContainer().getTargetById(fallingPlayerId_);
00104 if (target && target->getAlive())
00105 {
00106 FixedVector &position = getCurrentPosition();
00107 if (position[0] != 0 || position[1] != 0 || position[2] != 0)
00108 {
00109 target->getLife().setTargetPosition(position);
00110 }
00111 }
00112 else collision_ = true;
00113 }
00114
00115 PhysicsParticleReferenced::simulate(frameTime, remove);
00116 }
00117
00118 void TankFalling::collision(PhysicsParticleObject &position,
00119 ScorchedCollisionId collisionId)
00120 {
00121 Target *current = context_->getTargetContainer().getTargetById(fallingPlayerId_);
00122 if (current && current->getAlive())
00123 {
00124
00125 fixed dist = (tankStartPosition_ - position.getPosition()).Magnitude();
00126 fixed damage = dist * 20;
00127
00128
00129 fixed minDist = fixed(context_->getOptionsGame().
00130 getMinFallingDistance()) / 10;
00131 if (dist < minDist)
00132 {
00133
00134 damage = 0;
00135 }
00136 else if (current->getTargetState().getNoFallingDamage())
00137 {
00138 damage = 0;
00139 }
00140 if (parachute_)
00141 {
00142 fixed ParachuteThreshold = 0;
00143 if (dist >= ParachuteThreshold)
00144 {
00145
00146 damage = 0;
00147
00148
00149 if (!current->isTarget())
00150 {
00151 Tank *currentTank = (Tank *) current;
00152 currentTank->getAccessories().rm(parachute_->getParent(),
00153 parachute_->getParent()->getUseNumber());
00154 if (!currentTank->getAccessories().canUse(parachute_->getParent()))
00155 {
00156 current->getParachute().setCurrentParachute(0);
00157 }
00158 }
00159 }
00160 }
00161
00162 if (context_->getOptionsGame().getActionSyncCheck())
00163 {
00164 context_->getActionController().addSyncCheck(
00165 S3D::formatStringBuffer("TankFalling: %u %i, %i, %i",
00166 current->getPlayerId(),
00167 position.getPosition()[0].getInternal(),
00168 position.getPosition()[1].getInternal(),
00169 position.getPosition()[2].getInternal()));
00170 }
00171
00172
00173 current->getLife().setTargetPosition(position.getPosition());
00174
00175
00176 if (!current->isTarget())
00177 {
00178 DeformLandscape::flattenArea(*context_, position.getPosition());
00179 #ifndef S3D_SERVER
00180 if (!context_->getServerMode())
00181 {
00182 VisibilityPatchGrid::instance()->recalculateErrors(position.getPosition(), 2);
00183 }
00184 #endif
00185 }
00186
00187
00188 TargetDamageCalc::damageTarget(
00189 *context_,
00190 current, weapon_,
00191 weaponContext_, damage,
00192 false, false, false);
00193
00194
00195 std::map<unsigned int, Target *> collisionTargets;
00196 context_->getTargetSpace().getCollisionSet(
00197 current->getLife().getTargetPosition(), 3, collisionTargets, false);
00198 std::map<unsigned int, Target *>::iterator itor;
00199 for (itor = collisionTargets.begin();
00200 itor != collisionTargets.end();
00201 itor++)
00202 {
00203 Target *collisionTarget = (*itor).second;
00204
00205 if (current->isTarget() &&
00206 current->getTargetState().getDriveOverToDestroy() &&
00207 !collisionTarget->isTarget())
00208 {
00209
00210 WeaponFireContext weaponContext(weaponContext_);
00211 weaponContext.setPlayerId(collisionTarget->getPlayerId());
00212
00213 context_->getActionController().addAction(
00214 new TankDamage(weapon_, current->getPlayerId(), weaponContext,
00215 current->getLife().getLife(),
00216 false, false, false));
00217 }
00218 else if (collisionTarget->isTarget() &&
00219 collisionTarget->getTargetState().getDriveOverToDestroy() &&
00220 !current->isTarget())
00221 {
00222
00223 WeaponFireContext weaponContext(weaponContext_);
00224 weaponContext.setPlayerId(current->getPlayerId());
00225
00226 context_->getActionController().addAction(
00227 new TankDamage(weapon_,
00228 collisionTarget->getPlayerId(), weaponContext_,
00229 collisionTarget->getLife().getLife(),
00230 false, false, false));
00231 }
00232 }
00233 }
00234
00235 PhysicsParticleReferenced::collision(position, collisionId);
00236 }