Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- impulse and residualimpulse are float3
- GlobalConstants.h
- ...
- /**
- * maximum impulse strength an explosion is allowed to impart on a unit
- */
- const float MAX_EXPLOSION_IMPULSE = 1e4f;
- ...
- WeaponDefHandler.cpp
- ...
- wd.damages.impulseFactor = wdTable.GetFloat("impulseFactor", 1.0f);
- wd.damages.impulseBoost = wdTable.GetFloat("impulseBoost", 0.0f);
- wd.damages.craterMult = wdTable.GetFloat("craterMult", wd.damages.impulseFactor);
- wd.damages.craterBoost = wdTable.GetFloat("craterBoost", 0.0f);
- ...
- GameHelper.cpp
- void CGameHelper::DoExplosionDamage
- ...
- const float rawImpulseStrength = damages.impulseFactor * mod1 * (damages.GetDefaultDamage() + damages.impulseBoost)
- ...
- void CGameHelper::DoExplosionDamage(CFeature* feature,
- const float3& expPos, float expRad, const DamageArray& damages)
- ...
- float dmgScale = (damages.GetDefaultDamage() + damages.impulseBoost);
- ...
- MeleeWeapon.cpp->FireImpl()
- {
- if(targetType==Target_Unit){
- float3 impulseDir = targetUnit->pos-weaponMuzzlePos;
- impulseDir.Normalize();
- // the heavier the unit, the more impulse it does
- targetUnit->DoDamage(weaponDef->damages, owner, impulseDir * owner->mass * weaponDef->damages.impulseFactor, weaponDef->id);
- }
- }
- Unit.cpp
- void CUnit::Update()void CUnit::Update()
- ...
- // 0.968 ** 16 is slightly less than 0.6, which was the old value used in SlowUpdate
- residualImpulse *= 0.968f;
- ...
- void CUnit::DoDamage(const DamageArray& damages, CUnit* attacker, const float3& impulse, int weaponDefId)
- ...
- float impulseMult = 1.0f;
- ...
- AddImpulse((impulse * impulseMult) / mass);
- ...
- void CUnit::AddImpulse(const float3& addedImpulse) {
- residualImpulse += addedImpulse;
- if (addedImpulse.SqLength() >= 0.01f) {
- moveType->ImpulseAdded(addedImpulse);
- }
- }
- void CUnit::Kill(const float3& impulse, bool crushKill) {
- crushKilled = crushKill;
- DamageArray damage;
- DoDamage(damage * (health + 1.0f), NULL, impulse, -1);
- }
- MeleeWeapon.cpp
- void CMeleeWeapon::FireImpl()
- {
- if(targetType==Target_Unit){
- float3 impulseDir = targetUnit->pos-weaponMuzzlePos;
- impulseDir.Normalize();
- // the heavier the unit, the more impulse it does
- targetUnit->DoDamage(weaponDef->damages, owner, impulseDir * owner->mass * weaponDef->damages.impulseFactor, weaponDef->id);
- }
- }
- Feature.cpp
- void CFeature::DoDamage(const DamageArray& damages, const float3& impulse)
- ...
- residualImpulse = impulse;
- if (health <= 0 && def->destructable) {
- ...
- if (def->drawType >= DRAWTYPE_TREE) {
- if (impulse.SqLength2D() > 0.25f) {
- treeDrawer->AddFallingTree(pos, impulse, def->drawType - 1);
- }
- }
- }
- Unit.cpp->Update()
- // 0.968 ** 16 is slightly less than 0.6, which was the old value used in SlowUpdate
- residualImpulse *= 0.968f;
- GroundMoveType.cpp
- void CGroundMoveType::ImpulseAdded(const float3&)
- {
- // NOTE: ships must be able to receive impulse too (for collision handling)
- if (owner->beingBuilt)
- return;
- float3& impulse = owner->residualImpulse;
- float3& speed = owner->speed;
- if (skidding) {
- speed += impulse;
- impulse = ZeroVector;
- }
- const float3& groundNormal = ground->GetNormal(owner->pos.x, owner->pos.z);
- const float groundImpulseScale = impulse.dot(groundNormal);
- if (groundImpulseScale < 0.0f)
- impulse -= (groundNormal * groundImpulseScale);
- if (impulse.SqLength() <= 9.0f && groundImpulseScale <= 0.3f)
- return;
- skidding = true;
- useHeading = false;
- speed += impulse;
- impulse = ZeroVector;
- skidRotSpeed = 0.0f;
- skidRotAccel = 0.0f;
- float3 skidDir = owner->frontdir;
- if (speed.SqLength2D() >= 0.01f) {
- skidDir = speed;
- skidDir.y = 0.0f;
- skidDir.Normalize();
- }
- skidRotVector = skidDir.cross(UpVector);
- oldPhysState = owner->physicalState;
- owner->physicalState = CSolidObject::Flying;
- if (speed.dot(groundNormal) > 0.2f) {
- skidRotAccel = (gs->randFloat() - 0.5f) * 0.04f;
- flying = true;
- }
- ASSERT_SANE_OWNER_SPEED(speed);
- }
- void CGroundMoveType::CheckCollisionSkid()
- {
- CUnit* collider = owner;
- // NOTE:
- // the QuadField::Get* functions check o->midPos,
- // but the quad(s) that objects are stored in are
- // derived from o->pos (!)
- const float3& pos = collider->pos;
- const UnitDef* colliderUD = collider->unitDef;
- const vector<CUnit*>& nearUnits = qf->GetUnitsExact(pos, collider->radius);
- const vector<CFeature*>& nearFeatures = qf->GetFeaturesExact(pos, collider->radius);
- // magic number to reduce damage taken from collisions
- // between a very heavy and a very light CSolidObject
- static const float MASS_MULT = 0.02f;
- vector<CUnit*>::const_iterator ui;
- vector<CFeature*>::const_iterator fi;
- for (ui = nearUnits.begin(); ui != nearUnits.end(); ++ui) {
- CUnit* collidee = *ui;
- const UnitDef* collideeUD = collider->unitDef;
- const float sqDist = (pos - collidee->pos).SqLength();
- const float totRad = collider->radius + collidee->radius;
- if ((sqDist >= totRad * totRad) || (sqDist <= 0.01f)) {
- continue;
- }
- // stop units from reaching escape velocity
- const float3 dif = (pos - collidee->pos).SafeNormalize();
- if (collidee->mobility == NULL) {
- const float impactSpeed = -collider->speed.dot(dif);
- const float impactDamageMult = std::min(impactSpeed * collider->mass * MASS_MULT, MAX_UNIT_SPEED);
- const bool doColliderDamage = (modInfo.allowUnitCollisionDamage && impactSpeed > colliderUD->minCollisionSpeed && colliderUD->minCollisionSpeed >= 0.0f);
- const bool doCollideeDamage = (modInfo.allowUnitCollisionDamage && impactSpeed > collideeUD->minCollisionSpeed && collideeUD->minCollisionSpeed >= 0.0f);
- if (impactSpeed <= 0.0f)
- continue;
- collider->Move3D(dif * impactSpeed, true);
- collider->speed += ((dif * impactSpeed) * 1.8f);
- // damage the collider, no added impulse
- if (doColliderDamage) {
- collider->DoDamage(DamageArray(impactDamageMult), NULL, ZeroVector);
- }
- // damage the (static) collidee based on collider's mass, no added impulse
- if (doCollideeDamage) {
- collidee->DoDamage(DamageArray(impactDamageMult), NULL, ZeroVector);
- }
- } else {
- // don't conserve momentum
- assert(collider->mass > 0.0f && collidee->mass > 0.0f);
- const float impactSpeed = (collidee->speed - collider->speed).dot(dif) * 0.5f;
- const float colliderRelMass = (collider->mass / (collider->mass + collidee->mass));
- const float colliderRelImpactSpeed = impactSpeed * (1.0f - colliderRelMass);
- const float collideeRelImpactSpeed = impactSpeed * ( colliderRelMass);
- const float colliderImpactDmgMult = std::min(colliderRelImpactSpeed * collider->mass * MASS_MULT, MAX_UNIT_SPEED);
- const float collideeImpactDmgMult = std::min(collideeRelImpactSpeed * collider->mass * MASS_MULT, MAX_UNIT_SPEED);
- const float3 colliderImpactImpulse = dif * colliderRelImpactSpeed;
- const float3 collideeImpactImpulse = dif * collideeRelImpactSpeed;
- const bool doColliderDamage = (modInfo.allowUnitCollisionDamage && impactSpeed > colliderUD->minCollisionSpeed && colliderUD->minCollisionSpeed >= 0.0f);
- const bool doCollideeDamage = (modInfo.allowUnitCollisionDamage && impactSpeed > collideeUD->minCollisionSpeed && collideeUD->minCollisionSpeed >= 0.0f);
- if (impactSpeed <= 0.0f)
- continue;
- collider->Move3D(colliderImpactImpulse, true);
- collidee->Move3D(-collideeImpactImpulse, true);
- // damage the collider
- if (doColliderDamage) {
- collider->DoDamage(DamageArray(colliderImpactDmgMult), NULL, dif * colliderImpactDmgMult);
- }
- // damage the collidee
- if (doCollideeDamage) {
- collidee->DoDamage(DamageArray(collideeImpactDmgMult), NULL, dif * -collideeImpactDmgMult);
- }
- collider->speed += colliderImpactImpulse;
- collider->speed *= 0.9f;
- collidee->speed -= collideeImpactImpulse;
- collidee->speed *= 0.9f;
- }
- }
- for (fi = nearFeatures.begin(); fi != nearFeatures.end(); ++fi) {
- CFeature* f = *fi;
- if (!f->blocking)
- continue;
- const float sqDist = (pos - f->pos).SqLength();
- const float totRad = collider->radius + f->radius;
- if ((sqDist >= totRad * totRad) || (sqDist <= 0.01f))
- continue;
- const float3 dif = (pos - f->pos).SafeNormalize();
- const float impactSpeed = -collider->speed.dot(dif);
- const float impactDamageMult = std::min(impactSpeed * collider->mass * MASS_MULT, MAX_UNIT_SPEED);
- const float3 impactImpulse = dif * impactSpeed;
- const bool doColliderDamage = (modInfo.allowUnitCollisionDamage && impactSpeed > colliderUD->minCollisionSpeed && colliderUD->minCollisionSpeed >= 0.0f);
- if (impactSpeed <= 0.0f)
- continue;
- collider->Move3D(impactImpulse, true);
- collider->speed += (impactImpulse * 1.8f);
- // damage the collider, no added impulse (!)
- if (doColliderDamage) {
- collider->DoDamage(DamageArray(impactDamageMult), NULL, ZeroVector);
- }
- // damage the collidee feature based on collider's mass
- f->DoDamage(DamageArray(impactDamageMult), -impactImpulse);
- }
- ASSERT_SANE_OWNER_SPEED(collider->speed);
- }
- void CGroundMoveType::HandleUnitCollisions(
- CUnit* collider,
- const float3& colliderCurPos,
- const float3& colliderOldPos,
- const float colliderSpeed,
- const float colliderRadius,
- const float3& sepDirMask,
- const UnitDef* colliderUD,
- const MoveData* colliderMD,
- const CMoveMath* colliderMM
- ) {
- const float searchRadius = std::max(colliderSpeed, 1.0f) * (colliderRadius * 2.0f);
- const std::vector<CUnit*>& nearUnits = qf->GetUnitsExact(colliderCurPos, searchRadius);
- std::vector<CUnit*>::const_iterator uit;
- // NOTE: probably too large for most units (eg. causes tree falling animations to be skipped)
- const float3 crushImpulse = collider->speed * ((reversing)? -collider->mass: collider->mass);
- for (uit = nearUnits.begin(); uit != nearUnits.end(); ++uit) {
- CUnit* collidee = const_cast<CUnit*>(*uit);
- if (collidee == collider) { continue; }
- if (collidee->moveType->IsSkidding()) { continue; }
- if (collidee->moveType->IsFlying()) { continue; }
- const UnitDef* collideeUD = collidee->unitDef;
- const MoveData* collideeMD = collidee->mobility;
- const CMoveMath* collideeMM = (collideeMD != NULL)? collideeMD->moveMath: NULL;
- const float3& collideeCurPos = collidee->pos;
- const float3& collideeOldPos = collidee->moveType->oldPos;
- const bool colliderMobile = (collider->mobility != NULL);
- const bool collideeMobile = (collideeMD != NULL);
- const float collideeSpeed = collidee->speed.Length();
- const float collideeRadius = collideeMobile?
- FOOTPRINT_RADIUS(collideeMD->xsize, collideeMD->zsize):
- FOOTPRINT_RADIUS(collidee ->xsize, collidee ->zsize);
- bool pushCollider = colliderMobile;
- bool pushCollidee = (collideeMobile || collideeUD->canfly);
- bool crushCollidee = false;
- const float3 separationVector = colliderCurPos - collideeCurPos;
- const float separationMinDist = (colliderRadius + collideeRadius) * (colliderRadius + collideeRadius);
- if ((separationVector.SqLength() - separationMinDist) > 0.01f) { continue; }
- if (collidee->usingScriptMoveType) { pushCollidee = false; }
- if (collideeUD->pushResistant) { pushCollidee = false; }
- // if not an allied collision, neither party is allowed to be pushed (bi-directional)
- // if an allied collision, only the collidee is allowed to be crushed (uni-directional)
- const bool alliedCollision =
- teamHandler->Ally(collider->allyteam, collidee->allyteam) &&
- teamHandler->Ally(collidee->allyteam, collider->allyteam);
- pushCollider &= (alliedCollision || modInfo.allowPushingEnemyUnits);
- pushCollidee &= (alliedCollision || modInfo.allowPushingEnemyUnits);
- crushCollidee |= (!alliedCollision || modInfo.allowCrushingAlliedUnits);
- // don't push/crush either party if the collidee does not block the collider
- if (colliderMM->IsNonBlocking(*colliderMD, collidee)) { continue; }
- if (crushCollidee && !colliderMM->CrushResistant(*colliderMD, collidee)) { collidee->Kill(crushImpulse, true); }
- eventHandler.UnitUnitCollision(collider, collidee);
- const float sepDistance = (separationVector.Length() + 0.01f);
- const float penDistance = std::max((colliderRadius + collideeRadius) - sepDistance, 1.0f);
- const float sepResponse = std::min(SQUARE_SIZE * 2.0f, penDistance * 0.5f);
- const float3 sepDirection = (separationVector / sepDistance);
- const float3 colResponseVec = sepDirection * sepDirMask * sepResponse;
- const float
- m1 = collider->mass,
- m2 = collidee->mass,
- v1 = std::max(1.0f, colliderSpeed), // TODO: precalculate
- v2 = std::max(1.0f, collideeSpeed), // TODO: precalculate
- c1 = 1.0f + (1.0f - math::fabs(collider->frontdir.dot(-sepDirection))) * 5.0f,
- c2 = 1.0f + (1.0f - math::fabs(collidee->frontdir.dot( sepDirection))) * 5.0f,
- s1 = m1 * v1 * c1,
- s2 = m2 * v2 * c2;
- // far from a realistic treatment, but works
- const float collisionMassSum = s1 + s2 + 1.0f;
- float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s1 / collisionMassSum)));
- float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s2 / collisionMassSum)));
- if (!collideeMobile) {
- const float3 colliderNxtPos = colliderCurPos + collider->speed;
- const CMoveMath::BlockType colliderCurPosBits = colliderMM->IsBlocked(*colliderMD, colliderCurPos);
- const CMoveMath::BlockType colliderNxtPosBits = colliderMM->IsBlocked(*colliderMD, colliderNxtPos);
- if ((colliderCurPosBits & CMoveMath::BLOCK_STRUCTURE) == 0)
- continue;
- if ((colliderNxtPosBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
- // applied every frame objects are colliding, so be careful
- collider->AddImpulse(sepDirection * std::max(currentSpeed, accRate));
- collider->Move3D(collider->speed, true);
- }
- }
- const float3 colliderNewPos = colliderCurPos + (colResponseVec * colliderMassScale);
- const float3 collideeNewPos = collideeCurPos - (colResponseVec * collideeMassScale);
- // try to prevent both parties from being pushed onto non-traversable squares
- if ( (colliderMM->IsBlocked(*colliderMD, colliderNewPos) & CMoveMath::BLOCK_STRUCTURE) != 0) { colliderMassScale = 0.0f; }
- if (collideeMobile && (collideeMM->IsBlocked(*collideeMD, collideeNewPos) & CMoveMath::BLOCK_STRUCTURE) != 0) { collideeMassScale = 0.0f; }
- if ( colliderMM->GetPosSpeedMod(*colliderMD, colliderNewPos) <= 0.01f) { colliderMassScale = 0.0f; }
- if (collideeMobile && collideeMM->GetPosSpeedMod(*collideeMD, collideeNewPos) <= 0.01f) { collideeMassScale = 0.0f; }
- // ignore pushing contributions from idling collidee's
- if (collider->isMoving && !collidee->isMoving && alliedCollision) {
- colliderMassScale *= ((collideeMobile)? 0.0f: 1.0f);
- }
- if (pushCollider) { collider->Move3D( colResponseVec * colliderMassScale, true); } else if (colliderMobile) { collider->Move3D(colliderOldPos, false); }
- if (pushCollidee) { collidee->Move3D(-colResponseVec * collideeMassScale, true); } else if (collideeMobile) { collidee->Move3D(collideeOldPos, false); }
- #if 0
- if (!((gs->frameNum + collider->id) & 31) && !colliderCAI->unimportantMove) {
- // if we do not have an internal move order, tell units around us to bugger off
- // note: this causes too much chaos among the ranks when groups get large
- helper->BuggerOff(colliderCurPos + collider->frontdir * colliderRadius, colliderRadius, true, false, collider->team, collider);
- }
- #endif
- }
- }
- void CGroundMoveType::HandleFeatureCollisions(
- CUnit* collider,
- const float3& colliderCurPos,
- const float3& colliderOldPos,
- const float colliderSpeed,
- const float colliderRadius,
- const float3& sepDirMask,
- const UnitDef* colliderUD,
- const MoveData* colliderMD,
- const CMoveMath* colliderMM
- ) {
- const float searchRadius = std::max(colliderSpeed, 1.0f) * (colliderRadius * 2.0f);
- const std::vector<CFeature*>& nearFeatures = qf->GetFeaturesExact(colliderCurPos, searchRadius);
- std::vector<CFeature*>::const_iterator fit;
- const float3 crushImpulse = collider->speed * ((reversing)? -collider->mass: collider->mass);
- for (fit = nearFeatures.begin(); fit != nearFeatures.end(); ++fit) {
- CFeature* collidee = const_cast<CFeature*>(*fit);
- // const FeatureDef* collideeFD = collidee->def;
- const float3& collideeCurPos = collidee->pos;
- // const float collideeRadius = FOOTPRINT_RADIUS(collideeFD->xsize, collideeFD->zsize);
- const float collideeRadius = FOOTPRINT_RADIUS(collidee ->xsize, collidee ->zsize);
- const float3 separationVector = colliderCurPos - collideeCurPos;
- const float separationMinDist = (colliderRadius + collideeRadius) * (colliderRadius + collideeRadius);
- if ((separationVector.SqLength() - separationMinDist) > 0.01f) { continue; }
- if (colliderMM->IsNonBlocking(*colliderMD, collidee)) { continue; }
- if (!colliderMM->CrushResistant(*colliderMD, collidee)) { collidee->Kill(crushImpulse, true); }
- eventHandler.UnitFeatureCollision(collider, collidee);
- const float sepDistance = (separationVector.Length() + 0.01f);
- const float penDistance = std::max((colliderRadius + collideeRadius) - sepDistance, 1.0f);
- const float sepResponse = std::min(SQUARE_SIZE * 2.0f, penDistance * 0.5f);
- const float3 sepDirection = (separationVector / sepDistance);
- const float3 colResponseVec = sepDirection * sepDirMask * sepResponse;
- // multiply the collider's mass by a large constant (so that heavy
- // features do not bounce light units away like jittering pinballs;
- // collideeMassScale ~= 0.01 suppresses large responses)
- const float
- m1 = collider->mass,
- m2 = collidee->mass * 10000.0f,
- v1 = std::max(1.0f, colliderSpeed),
- v2 = 1.0f,
- c1 = (1.0f - math::fabs( collider->frontdir.dot(-sepDirection))) * 5.0f,
- c2 = (1.0f - math::fabs(-collider->frontdir.dot( sepDirection))) * 5.0f,
- s1 = m1 * v1 * c1,
- s2 = m2 * v2 * c2;
- const float collisionMassSum = s1 + s2 + 1.0f;
- const float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s1 / collisionMassSum)));
- // const float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s2 / collisionMassSum)));
- if (collidee->reachedFinalPos) {
- const float3 colliderNxtPos = colliderCurPos + collider->speed;
- const CMoveMath::BlockType colliderCurPosBits = colliderMM->IsBlocked(*colliderMD, colliderCurPos);
- const CMoveMath::BlockType colliderNxtPosBits = colliderMM->IsBlocked(*colliderMD, colliderNxtPos);
- if ((colliderCurPosBits & CMoveMath::BLOCK_STRUCTURE) == 0)
- continue;
- if ((colliderNxtPosBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
- // applied every frame objects are colliding, so be careful
- collider->AddImpulse(sepDirection * std::max(currentSpeed, accRate));
- collider->Move3D(collider->speed, true);
- }
- }
- collider->Move3D(colResponseVec * colliderMassScale, true);
- }
- }
- StrafeAirMoveType.cpp
- void CStrafeAirMoveType::ImpulseAdded(const float3&)
- {
- if (aircraftState == AIRCRAFT_FLYING) {
- owner->speed += owner->residualImpulse;
- owner->residualImpulse = ZeroVector;
- }
- }
- UnitScript.cpp
- void CUnitScript::Explode(int piece, int flags)
- ...
- // This means that we are going to do a full fledged piece explosion!
- float3 baseSpeed = unit->speed + unit->residualImpulse * 0.5f;
- float sql = baseSpeed.SqLength();
- ...
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement