Skip to content

Instantly share code, notes, and snippets.

@Rseding91
Last active July 15, 2018 17:04
Show Gist options
  • Save Rseding91/aa5df1346f35537b382cf453de9bda94 to your computer and use it in GitHub Desktop.
Save Rseding91/aa5df1346f35537b382cf453de9bda94 to your computer and use it in GitHub Desktop.
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