Last active
July 15, 2018 17:04
-
-
Save Rseding91/aa5df1346f35537b382cf453de9bda94 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void Car::update() | |
{ | |
if (this->tickOfLastUpdate == this->getEntityTick()) | |
return; | |
this->tickOfLastUpdate = this->getEntityTick(); | |
if (!this->hasBeltImmunity()) | |
this->moveByTransportBelt(); | |
const CarPrototype& prototype = *this->getPrototype(); | |
if (this->speed != 0 || | |
this->ridingState.accelerationState != RidingState::AccelerationState::Nothing || | |
this->ridingState.direction != RidingState::Direction::None) | |
{ | |
this->energySource->update(this, | |
this->ridingState.accelerationState != RidingState::AccelerationState::Nothing || | |
prototype.tankDriving && this->ridingState.direction != RidingState::Direction::None); | |
/* Here the energy can be negative, meaning that we are going backwards. */ | |
Energy energy = (3600 * 0.5) * prototype.weight * this->speed * Math::fabs(this->speed); | |
double speedBonus = this->getSpeedBonusAndExtractEnergy(); | |
double fuelSpeedModifer = this->energySource->isBurnerSource() ? static_cast<Burner*>(this->energySource)->getCurrentFuelAccelerationModifier() : 1; | |
if (!this->energySource->isEmpty() && | |
(this->ridingState.accelerationState == RidingState::AccelerationState::Accelerating || | |
this->ridingState.accelerationState == RidingState::AccelerationState::Reversing)) | |
{ | |
Energy energyRequested = prototype.consumption * this->consumptionModifier; | |
Energy energyGained; | |
if (this->ridingState.accelerationState == RidingState::AccelerationState::Accelerating) | |
energyGained = this->energySource->extractEnergyAndPollute(energyRequested, this->getChunk()); | |
else | |
energyGained = -this->energySource->extractEnergyAndPollute(energyRequested * 0.5, this->getChunk()); | |
energyGained *= prototype.effectivity * this->effectivityModifier; | |
energyGained *= fuelSpeedModifer; | |
energyGained *= speedBonus; | |
energy += energyGained; | |
} | |
else if (this->ridingState.accelerationState == RidingState::AccelerationState::Braking) | |
{ | |
if (energy > 0 && energy > prototype.brakingForce) | |
energy -= prototype.brakingForce; | |
else if (energy < 0 && -energy > prototype.brakingForce) | |
energy += prototype.brakingForce; | |
else | |
energy = 0; | |
} | |
double friction = (1 - prototype.frictionForce * (1 + prototype.terrainFrictionModifier * (this->calculateTerrainFrictionModifier() - 1)) * this->frictionModifier); | |
energy *= friction * friction; | |
double desiredOrientationChange = 0; | |
double desiredSpeed; | |
double absSpeed = Math::sqrt(Math::fabs(energy / (3600 * 0.5 * prototype.weight))); | |
if (energy >= 0) | |
desiredSpeed = absSpeed; | |
else | |
desiredSpeed = -absSpeed; | |
if (this->ridingState.direction != RidingState::Direction::None) | |
{ | |
desiredOrientationChange = prototype.rotationSpeed; | |
if (!prototype.tankDriving) | |
{ | |
desiredOrientationChange *= Math::sqrt(absSpeed); | |
if (energy < 0) | |
desiredOrientationChange *= -1; | |
} | |
else | |
{ | |
if (!this->energySource->isEmpty()) | |
{ | |
// Half speed bonus because it "feels" nice compared to everything else. | |
if (speedBonus != 1.0) | |
desiredOrientationChange *= 1 + speedBonus * 0.5; | |
if (this->ridingState.accelerationState == RidingState::AccelerationState::Nothing) // consume fuel when turning and not accelerating | |
this->energySource->extractEnergyAndPollute(prototype.consumption * this->consumptionModifier, this->getChunk()); | |
} | |
else if (absSpeed <= 1e-6) // no tank turning when out of fuel and not moving | |
desiredOrientationChange = 0; | |
} | |
} | |
if (absSpeed > 1e-6 || desiredOrientationChange > 1e-6) | |
{ | |
if (this->ridingState.direction == RidingState::Direction::Left) | |
desiredOrientationChange *= -1; | |
this->moveCar(desiredSpeed, desiredOrientationChange); | |
this->orientation = this->boundingBox.getOrientation(); | |
this->baseAnimationPosition.move(absSpeed, prototype.animation.animations[0]); | |
if (prototype.turretAnimation.loaded()) | |
this->turretAnimationPosition.move(absSpeed, prototype.turretAnimation.animations[0]); | |
} | |
else | |
this->speed = 0; | |
} | |
if (this->shooter) | |
this->shooter->update(nullptr, | |
this->getActiveGun(), | |
this->getSurface(), | |
this->getForce(), | |
Vector(this->speed, this->getBoundingBox().getOrientation()), | |
// ignoreTargetDistance | |
false, | |
this->position); | |
if (!this->shootingTarget.isZero()) | |
this->shoot(this->getShootingCharacter()); | |
else if (this->getEntityTick() > this->tickOfLastTurretRotation + prototype.turretReturnTimeout && | |
this->relativeTurretOrientation != 0) | |
this->returnTurret(); | |
super::update(); | |
} | |
void Car::moveCar(double desiredSpeed, double desiredOrientationChange) | |
{ | |
// NOTE: most of these calculations are not scientifically correct, this is for for simplification and gameplay | |
const CarPrototype& prototype = *this->getPrototype(); | |
double pushDamageModifier = 0.5; // how much damage does the acceleration power do. Determines the damage when accelerating when standing still | |
double acceleration = (desiredSpeed - this->speed); | |
if (desiredSpeed < 0) | |
acceleration = -acceleration; | |
double initialEnergy = this->speed * this->speed * prototype.weight | |
+ (acceleration * acceleration * prototype.weight * pushDamageModifier) | |
// scientifically correct would be (orientationChange*2*PI*(distance from center to the collision)) | |
+ desiredOrientationChange * desiredOrientationChange * prototype.weight * pushDamageModifier; | |
double remainingEnergy = initialEnergy; | |
if (initialEnergy <= 0) // we are not moving nor accelerating | |
return; | |
Vector forward(1, this->boundingBox.getOrientation()); | |
Vector movement = forward * desiredSpeed; | |
BoundingBox rotatedCollisionBox = this->boundingBox; | |
rotatedCollisionBox.orientation += desiredOrientationChange; | |
BoundingBox desiredBoundingBox = rotatedCollisionBox + movement; | |
if (this->getSurface().mutableCollideWithTile(desiredBoundingBox, this->collisionMask)) | |
{ | |
this->speed = 0; | |
return; | |
} | |
for (Entity* entity: EntitySearch(this->getSurface(), desiredBoundingBox, this->collisionMask)) | |
{ | |
if (entity == this) | |
continue; | |
if (entity->isCliff()) | |
{ | |
if (Math::fabs(this->getSpeed()) > 0.05) | |
if (const Sound* vehicleImpactSound = entity->getPrototype()->getVehicleImpactSound()) | |
this->getGame()->playSound(*vehicleImpactSound, this->getSurface().index, this->position); | |
this->speed = 0; | |
return; | |
} | |
DamageHit damageHit(Damage(remainingEnergy / prototype.energyPerHitPoint, CorePrototypes::impactDamage->getID()), this->getForce()); | |
damageHit.dealer = this; | |
float damageBefore = entity->getHealth(); | |
double damageDealt = entity->damage(damageHit); | |
double damageReceived = 0; | |
if (entity->getHealthRatio() > 0 || damageBefore == 0) | |
{ | |
assert(damageBefore > 0 || entity->getMaxHealth() == 0); | |
remainingEnergy = 0; | |
if (!this->getPrototype()->immuneToTreeImpacts || !entity->isTree()) | |
damageReceived = this->damage(damageHit); | |
} | |
else | |
{ | |
remainingEnergy -= damageBefore * prototype.energyPerHitPoint; | |
if (!this->getPrototype()->immuneToTreeImpacts || !entity->isTree()) | |
{ | |
DamageHit vehicleHit(Damage(damageBefore, CorePrototypes::impactDamage->getID()), this->getForce()); | |
damageReceived = this->damage(vehicleHit); | |
} | |
} | |
if ((damageDealt || damageReceived) && Math::fabs(this->getSpeed()) > 0.05) | |
{ | |
this->getPrototype()->crashTrigger.apply(this->getSurface(), | |
Vector(this->getSpeed(), this->getOrientation()), | |
this, | |
entity, | |
TriggerModifier(this->getForce())); | |
if (const Sound* vehicleImpactSound = entity->getPrototype()->getVehicleImpactSound()) | |
this->getGame()->playSound(*vehicleImpactSound, this->getSurface().index, this->position); | |
} | |
if (remainingEnergy <= 0) | |
{ | |
remainingEnergy = 0; | |
break; | |
} | |
} | |
this->speed = (remainingEnergy / initialEnergy) * desiredSpeed; | |
if (initialEnergy - remainingEnergy == 0) // we did not hit anything | |
{ | |
RealOrientation newOrientation = this->boundingBox.getOrientation() + desiredOrientationChange; | |
if (this->canChangePosition(movement, newOrientation)) | |
{ | |
this->changePositionAndOrientation(movement, newOrientation); | |
if (!this->position.isReasonable()) | |
LOG_AND_ABORT("receiveMovementImpulse of %s ended up with unreasonable position", this->getPrototype()->name.c_str()); | |
} | |
else | |
if (remainingEnergy > 0) | |
this->moveCar(this->speed, desiredOrientationChange); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment