Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- New `Attachable` INI and Lua (R/W) properties `InheritsVelWhenDetached` and `InheritsAngularVelWhenDetached`, which determine how much of these velocities an attachable inherits from its parent when detached. Defaults to 1.

- New `ACraft` INI and Lua (R/W) property `CanEnterOrbit`, which determines whether a craft can enter orbit (and refund gold appropriately) or not. If false, default out-of-bounds deletion logic applies.

</details>

<details><summary><b>Changed</b></summary>
Expand Down Expand Up @@ -113,14 +115,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- Internal GUI element `ComboBox` no longer displays dropdown combobutton when disabled, to communicate visually that it's setting is not modifiable.

- Almost all ctrl+* special inputs functionality (i.e restarting activity, world dumps, showing performance stats) are now mapped to right alt, to not interfere with default crouching inputs. The only exception is ctrl+arrow keys for changing console size.
- Almost all ctrl+\* special inputs functionality (i.e restarting activity, world dumps, showing performance stats) are now mapped to right alt, to not interfere with default crouching inputs. The only exception is ctrl+arrow keys for changing console size.

- `Gib`s and detached `Attachable`s now inherit the parent's angular velocity by default.

- `InheritsVel` now accounts for the angular velocity of the parent MO, resulting in offset gibs and emissions being flung further away.

- `InheritsVel` and its ilk have been uncapped, allowing users to set them outside of 0-1.

- `Scene` Lua functions `AddNavigatableArea(areaName)` and `ClearNavigatableAreas()` have been renamed/corrected to `AddNavigableArea(areaName)` and `ClearNavigableAreas()`, respectively.

</details>

<details><summary><b>Fixed</b></summary>
Expand Down
12 changes: 6 additions & 6 deletions Data/Base.rte/AI/SharedBehaviors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -864,28 +864,28 @@ function SharedBehaviors.GoToWpt(AI, Owner, Abort)

-- test jumping
local JetAccel = Accel + Vector(-jetStrength, 0):RadRotate(Owner.RotAngle+1.375*math.pi+Owner:GetAimAngle(false)*0.25);
local JumpPos = Owner.Head.Pos + PixelVel + JetAccel * (t*t*0.5);
local JumpPos = (Owner.Head and Owner.Head.Pos or Owner.Pos) + PixelVel + JetAccel * (t*t*0.5);

-- a burst add a one time boost to acceleration
if Owner.Jetpack:CanTriggerBurst() then
JumpPos = JumpPos + Vector(-AI.jetBurstFactor, 0):AbsRotateTo(JetAccel);
end

-- check for obstacles from the head
Trace = SceneMan:ShortestDistance(Owner.Head.Pos, JumpPos, false);
local jumpScore = SceneMan:CastObstacleRay(Owner.Head.Pos, Trace, JumpPos, Vector(), Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 3);
Trace = SceneMan:ShortestDistance((Owner.Head and Owner.Head.Pos or Owner.Pos), JumpPos, false);
local jumpScore = SceneMan:CastObstacleRay((Owner.Head and Owner.Head.Pos or Owner.Pos), Trace, JumpPos, Vector(), Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 3);
if jumpScore < 0 then -- no obstacles: calculate the distance from the future pos to the wpt
jumpScore = SceneMan:ShortestDistance(Waypoint.Pos, JumpPos, false).Magnitude;
else -- the ray hit terrain or start inside terrain: avoid
jumpScore = SceneMan:ShortestDistance(Waypoint.Pos, JumpPos, false).Largest * 2;
end

-- test falling
local FallPos = Owner.Head.Pos + PixelVel + Accel * (t*t*0.5);
local FallPos = (Owner.Head and Owner.Head.Pos or Owner.Pos) + PixelVel + Accel * (t*t*0.5);

-- check for obstacles when falling/walking
local Trace = SceneMan:ShortestDistance(Owner.Head.Pos, FallPos, false);
SceneMan:CastObstacleRay(Owner.Head.Pos, Trace, FallPos, Vector(), Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 3);
local Trace = SceneMan:ShortestDistance((Owner.Head and Owner.Head.Pos or Owner.Pos), FallPos, false);
SceneMan:CastObstacleRay((Owner.Head and Owner.Head.Pos or Owner.Pos), Trace, FallPos, Vector(), Owner.ID, Owner.IgnoresWhichTeam, rte.grassID, 3);

if SceneMan:ShortestDistance(Waypoint.Pos, FallPos, false):MagnitudeIsLessThan(jumpScore) then
AI.jump = false;
Expand Down
3 changes: 2 additions & 1 deletion Data/Browncoats.rte/Activities.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

AddActivity = GAScripted
PresetName = Refinery Assault
Description = Test your arsenal in peace and quiet witout any enemies.
Description = Test your arsenal in war and chaos with a lot of enemies.
SceneName = Yskely Refinery
TeamOfPlayer1 = 0
TeamOfPlayer2 = 0
Expand All @@ -15,6 +15,7 @@ AddActivity = GAScripted
Team2Funds = 100
DeployUnitsSwitchEnabled = 0
ScriptPath = Browncoats.rte/Activities/RefineryAssault.lua
AddRequiredArea = CaptureArea_RefineryLCHackConsole1 // a little arbitrary, but it works.
LuaClassName = RefineryAssault
DefaultDeployUnits = 1
DefaultFogOfWar = 1
8 changes: 4 additions & 4 deletions Data/Browncoats.rte/Activities/RefineryAssault.lua
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ function RefineryAssault:StartActivity(newGame)
end
end

SceneMan.Scene:AddNavigatableArea("Mission Stage Area 1");
SceneMan.Scene:AddNavigatableArea("Mission Stage Area 2");
SceneMan.Scene:AddNavigatableArea("Mission Stage Area 3");
SceneMan.Scene:AddNavigatableArea("Mission Stage Area 4");
SceneMan.Scene:AddNavigableArea("Mission Stage Area 1");
SceneMan.Scene:AddNavigableArea("Mission Stage Area 2");
SceneMan.Scene:AddNavigableArea("Mission Stage Area 3");
SceneMan.Scene:AddNavigableArea("Mission Stage Area 4");

self.musicGraceTimer = Timer();
self.musicGraceTime = 4000;
Expand Down
39 changes: 24 additions & 15 deletions Source/Entities/ACraft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ void ACraft::Clear() {
m_DeliveryState = FALL;
m_AltitudeMoveState = HOVER;
m_AltitudeControl = 0;
m_CanEnterOrbit = true;
m_MaxPassengers = -1;

m_DeliveryDelayMultiplier = 1.0;
Expand Down Expand Up @@ -251,6 +252,7 @@ int ACraft::Create(const ACraft& reference) {
m_DeliveryState = reference.m_DeliveryState;
m_AltitudeMoveState = reference.m_AltitudeMoveState;
m_AltitudeControl = reference.m_AltitudeControl;
m_CanEnterOrbit = reference.m_CanEnterOrbit;
m_MaxPassengers = reference.m_MaxPassengers;

m_DeliveryDelayMultiplier = reference.m_DeliveryDelayMultiplier;
Expand Down Expand Up @@ -285,6 +287,7 @@ int ACraft::ReadProperty(const std::string_view& propName, Reader& reader) {
MatchProperty("DeliveryDelayMultiplier", { reader >> m_DeliveryDelayMultiplier; });
MatchProperty("ExitInterval", { reader >> m_ExitInterval; });
MatchProperty("CanLand", { reader >> m_LandingCraft; });
MatchProperty("CanEnterOrbit", { reader >> m_CanEnterOrbit; });
MatchProperty("MaxPassengers", { reader >> m_MaxPassengers; });
MatchProperty("ScuttleIfFlippedTime", { reader >> m_ScuttleIfFlippedTime; });
MatchProperty("ScuttleOnDeath", { reader >> m_ScuttleOnDeath; });
Expand Down Expand Up @@ -314,7 +317,10 @@ int ACraft::Save(Writer& writer) const {

writer.NewProperty("CrashSound");
writer << m_CrashSound;


writer.NewProperty("CanEnterOrbit");
writer << m_CanEnterOrbit;

writer.NewProperty("MaxPassengers");
writer << m_MaxPassengers;
writer.NewProperty("ScuttleIfFlippedTime");
Expand Down Expand Up @@ -698,23 +704,26 @@ void ACraft::Update() {
/////////////////////////////////////////
// Check for having gone into orbit

if (m_Pos.m_Y < -m_CharHeight || m_Pos.m_Y > g_SceneMan.GetSceneHeight() + m_CharHeight) {
g_ActivityMan.GetActivity()->HandleCraftEnteringOrbit(this);
// Play fading away thruster sound
// if (m_pMThruster && m_pMThruster->IsEmitting())
// m_pMThruster->(pTargetBitmap, targetPos, mode, onlyPhysical);
m_ToDelete = true;
}
if (m_CanEnterOrbit) {
if (m_Pos.m_Y < -m_CharHeight || m_Pos.m_Y > g_SceneMan.GetSceneHeight() + m_CharHeight) {
g_ActivityMan.GetActivity()->HandleCraftEnteringOrbit(this);
// Play fading away thruster sound
// if (m_pMThruster && m_pMThruster->IsEmitting())
// m_pMThruster->(pTargetBitmap, targetPos, mode, onlyPhysical);
m_ToDelete = true;
}

if (g_ActivityMan.GetActivity()->GetCraftOrbitAtTheEdge()) {
if (g_SceneMan.GetScene() && !g_SceneMan.GetScene()->WrapsX()) {
if (m_Pos.m_X < -GetSpriteWidth() || m_Pos.m_X > g_SceneMan.GetSceneWidth() + GetSpriteWidth()) {
g_ActivityMan.GetActivity()->HandleCraftEnteringOrbit(this);
m_ToDelete = true;
// Horizontal orbiting, if scene doesn't wrap
if (g_ActivityMan.GetActivity()->GetCraftOrbitAtTheEdge()) {
if (g_SceneMan.GetScene() && !g_SceneMan.GetScene()->WrapsX()) {
if (m_Pos.m_X < -GetSpriteWidth() || m_Pos.m_X > g_SceneMan.GetSceneWidth() + GetSpriteWidth()) {
g_ActivityMan.GetActivity()->HandleCraftEnteringOrbit(this);
m_ToDelete = true;
}
}
}
}
}

if (m_Status == DEAD) {
if (m_ScuttleOnDeath || m_AIMode == AIMODE_SCUTTLE) {
GibThis();
Expand Down
12 changes: 12 additions & 0 deletions Source/Entities/ACraft.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,16 @@ namespace RTE {
/// get drawn etc.
void DrawHUD(BITMAP* pTargetBitmap, const Vector& targetPos = Vector(), int whichScreen = 0, bool playerControlled = false) override;

/// Gets whether this craft can enter orbit and refund the owning team when out of the map. If false,
/// only default out-of-bounds deletion logic applies.
/// @return Whether this craft can enter orbit or not.
bool GetCanEnterOrbit() const { return m_CanEnterOrbit; }

/// Sets whether this craft can enter orbit and refund the owning team when out of the map. If false,
/// only default out-of-bounds deletion logic applies.
/// @param canEnterOrbit Whether this craft can enter orbit or not.
void SetCanEnterOrbit(bool canEnterOrbit) { m_CanEnterOrbit = canEnterOrbit; }

/// The recomended, not absolute, maximum number of actors that fit in the
/// invetory. Used by the activity AI.
/// @return An integer with the recomended number of actors that fit in the craft.
Expand Down Expand Up @@ -354,6 +364,8 @@ namespace RTE {
Timer m_CrashTimer;
// Crash sound
SoundContainer* m_CrashSound;
// Whether this can enter orbit and refund the owning team. If false, will use default out-of-bounds deletion behavior.
bool m_CanEnterOrbit;
// The maximum number of actors that fit in the inventory
int m_MaxPassengers;
int m_ScuttleIfFlippedTime; //!< The time after which the craft will scuttle automatically, if tipped over.
Expand Down
3 changes: 3 additions & 0 deletions Source/Entities/Actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ int Actor::ReadProperty(const std::string_view& propName, Reader& reader) {
MatchProperty("StableRecoveryDelay", { reader >> m_StableRecoverDelay; });
MatchProperty("CanRun", { reader >> m_CanRun; });
MatchProperty("CrouchWalkSpeedMultiplier", { reader >> m_CrouchWalkSpeedMultiplier; });
MatchProperty("GoldCarried", { reader >> m_GoldCarried; });
MatchProperty("AimAngle", { reader >> m_AimAngle; });
MatchProperty("AimRange", { reader >> m_AimRange; });
MatchProperty("AimDistance", { reader >> m_AimDistance; });
Expand Down Expand Up @@ -413,6 +414,8 @@ int Actor::Save(Writer& writer) const {
writer << m_CanRun;
writer.NewProperty("CrouchWalkSpeedMultiplier");
writer << m_CrouchWalkSpeedMultiplier;
writer.NewProperty("GoldCarried");
writer << m_GoldCarried;
writer.NewProperty("AimAngle");
writer << m_AimAngle;
writer.NewProperty("AimRange");
Expand Down
30 changes: 13 additions & 17 deletions Source/Entities/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ void Scene::Clear() {
m_ScanScheduled[team] = false;
}
m_AreaList.clear();
m_NavigatableAreas.clear();
m_NavigatableAreasUpToDate = false;
m_NavigableAreas.clear();
m_NavigableAreasUpToDate = false;
m_GlobalAcc.Reset();
m_SelectedAssemblies.clear();
m_AssembliesCounts.clear();
Expand Down Expand Up @@ -1848,29 +1848,25 @@ bool Scene::SetArea(Area& newArea) {
return false;
}

bool Scene::HasArea(std::string areaName) {
bool Scene::HasArea(const std::string& areaName) {
for (std::list<Area>::iterator aItr = m_AreaList.begin(); aItr != m_AreaList.end(); ++aItr) {
if ((*aItr).GetName() == areaName)
return true;
}
return false;
}

Scene::Area* Scene::GetArea(const std::string_view& areaName, bool required) {
Scene::Area* Scene::GetArea(const std::string& areaName) {
for (Scene::Area& area: m_AreaList) {
if (area.GetName() == areaName) {
return &area;
}
}

if (required) {
g_ConsoleMan.PrintString("WARNING: Could not find the requested Scene Area named : " + std::string(areaName));
}

return nullptr;
}

bool Scene::RemoveArea(std::string areaName) {
bool Scene::RemoveArea(const std::string& areaName) {
for (std::list<Area>::iterator aItr = m_AreaList.begin(); aItr != m_AreaList.end(); ++aItr) {
if ((*aItr).GetName() == areaName) {
m_AreaList.erase(aItr);
Expand All @@ -1880,7 +1876,7 @@ bool Scene::RemoveArea(std::string areaName) {
return false;
}

bool Scene::WithinArea(std::string areaName, const Vector& point) const {
bool Scene::WithinArea(const std::string& areaName, const Vector& point) const {
if (areaName.empty())
return false;

Expand Down Expand Up @@ -2438,21 +2434,21 @@ void Scene::Update() {
}
}

if (m_NavigatableAreasUpToDate == false) {
if (m_NavigableAreasUpToDate == false) {
// Need to block until all current pathfinding requests are finished. Ugh, if only we had a better way (interrupt/cancel a path request to start a new one?)
// TODO: Make the PathRequest struct more capable and maybe we can delay starting or cancel mid-request?
BlockUntilAllPathingRequestsComplete();

m_NavigatableAreasUpToDate = true;
m_NavigableAreasUpToDate = true;
for (int team = Activity::Teams::NoTeam; team < Activity::Teams::MaxTeamCount; ++team) {
PathFinder& pathFinder = GetPathFinder(static_cast<Activity::Teams>(team));

pathFinder.MarkAllNodesNavigatable(m_NavigatableAreas.empty());
pathFinder.MarkAllNodesNavigable(m_NavigableAreas.empty());

for (const std::string& navigatableArea: m_NavigatableAreas) {
if (HasArea(navigatableArea)) {
for (const Box& navigatableBox: GetArea(navigatableArea)->GetBoxes()) {
pathFinder.MarkBoxNavigatable(navigatableBox, true);
for (const std::string& navigableArea: m_NavigableAreas) {
if (HasArea(navigableArea)) {
for (const Box& navigableBox: GetArea(navigableArea)->GetBoxes()) {
pathFinder.MarkBoxNavigable(navigableBox, true);
}
}
}
Expand Down
32 changes: 13 additions & 19 deletions Source/Entities/Scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,39 +501,33 @@ namespace RTE {
/// This won't throw any errors to the console if the Area isn't found.
/// @param areaName The name of the Area to try to find in this Scene.
/// @return Whether the specified area is defined in this Scene.
bool HasArea(std::string areaName);
bool HasArea(const std::string& areaName);

/// Gets a specified Area identified by name. Ownership is NOT transferred!
/// @param areaName The name of the Area to try to get.
/// @param required Whether the area is required, and should throw an error if not found.
/// @return A pointer to the Area asked for, or nullptr if no Area of that name was found.
Area* GetArea(const std::string_view& areaName, bool required);
Area* GetArea(const std::string& areaName);

/// Gets a specified Area identified by name. Ownership is NOT transferred!
/// @param areaName The name of the Area to try to get.
/// @return A pointer to the Area asked for, or nullptr if no Area of that name was found.
Area* GetArea(const std::string& areaName) { return GetArea(areaName, true); }

void AddNavigatableArea(const std::string& areaName) {
m_NavigatableAreas.push_back(areaName);
m_NavigatableAreasUpToDate = false;
void AddNavigableArea(const std::string& areaName) {
m_NavigableAreas.push_back(areaName);
m_NavigableAreasUpToDate = false;
}
void ClearNavigatableAreas(const std::string& areaName) {
m_NavigatableAreas.clear();
m_NavigatableAreasUpToDate = false;
void ClearNavigableAreas() {
m_NavigableAreas.clear();
m_NavigableAreasUpToDate = false;
}

/// Removes a specific Area identified by a name.
/// @param areaName The name of the Area to try to remove.
/// @return Whether an Area of that name was found, and subsequently removed.
bool RemoveArea(std::string areaName);
bool RemoveArea(const std::string& areaName);

/// Checks if a point is within a specific named Area of this Scene. If
/// no Area of the name is found, this just returns false without error.
/// @param areaName The name of the Area to try to check against.
/// @param point The point to see if it's within the specified Area.
/// @return Whether any Area of that name was found, AND the point falls within it.
bool WithinArea(std::string areaName, const Vector& point) const;
bool WithinArea(const std::string& areaName, const Vector& point) const;

/// Gets the global acceleration (in m/s^2) that is applied to all movable
/// objects' velocities during every frame. Typically models gravity.
Expand Down Expand Up @@ -765,9 +759,9 @@ namespace RTE {
// List of all the specified Area's of the scene
std::list<Area> m_AreaList;

// List of navigatable areas in the scene. If this list is empty, the entire scene is assumed to be navigatable
std::vector<std::string> m_NavigatableAreas;
bool m_NavigatableAreasUpToDate;
// List of navigable areas in the scene. If this list is empty, the entire scene is assumed to be navigable
std::vector<std::string> m_NavigableAreas;
bool m_NavigableAreasUpToDate;

// The global acceleration vector in m/s^2. (think gravity/wind)
Vector m_GlobalAcc;
Expand Down
7 changes: 4 additions & 3 deletions Source/Lua/LuaBindingsEntities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ACraft) {
.property("HatchOpenSound", &ACraft::GetHatchOpenSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchOpenSound)
.property("HatchCloseSound", &ACraft::GetHatchCloseSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchCloseSound)
.property("CrashSound", &ACraft::GetCrashSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetCrashSound)
.property("CanEnterOrbit", &ACraft::GetCanEnterOrbit, &ACraft::SetCanEnterOrbit)
.property("MaxPassengers", &ACraft::GetMaxPassengers)
.property("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier)
.property("ScuttleOnDeath", &ACraft::GetScuttleOnDeath, &ACraft::SetScuttleOnDeath)
Expand Down Expand Up @@ -1196,10 +1197,10 @@ LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Scene) {
.def_readwrite("Areas", &Scene::m_AreaList, luabind::return_stl_iterator)
.def("SetArea", &Scene::SetArea)
.def("HasArea", &Scene::HasArea)
.def("GetArea", (Scene::Area * (Scene::*)(const std::string& areaName)) & Scene::GetArea)
.def("GetArea", &Scene::GetArea)
.def("WithinArea", &Scene::WithinArea)
.def("AddNavigatableArea", &Scene::AddNavigatableArea)
.def("ClearNavigatableAreas", &Scene::ClearNavigatableAreas)
.def("AddNavigableArea", &Scene::AddNavigableArea)
.def("ClearNavigableAreas", &Scene::ClearNavigableAreas)
.def("ResetPathFinding", &Scene::ResetPathFinding)
.def("UpdatePathFinding", &Scene::UpdatePathFinding)
.def("PathFindingUpdated", &Scene::PathFindingUpdated)
Expand Down
Loading