-
Notifications
You must be signed in to change notification settings - Fork 104
bugfix: Propaganda effects no longer persist for contained units with direct propaganda tower behaviour modules #1545
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
… direct propaganda tower behaviour modules
ad11b89
to
198e8c8
Compare
This change correctly identifies the cause of the issue, but the fix is not properly implemented. The KindOf inside the Contain module is configurable in INI:
Therefore, hardcoding this KindOf is not right. The correct way to test is in the contain module via Therefore, I have created new change #1609. |
Oh right, |
I believe I have figured out a more comprehensive solution that covers all cases. PROP.mp4 |
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/PropagandaTowerBehavior.cpp
Outdated
Show resolved
Hide resolved
// If our container is contained, we turn the heck off. Seems like a weird specific check, but all of | ||
// attacking is guarded by the same check in isPassengersAllowedToFire. We similarly work in a container, | ||
// but not in a double container. | ||
// If our container or any parent containers are an enclosing container, we turn the heck off. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest
// TheSuperHackers @bugfix If our container or any parent containers are enclosing, we turn the heck off.
and move comment below #else
?
|
||
for (Object* child = self, *container = self->getContainedBy(); container; child = container, container = container->getContainedBy()) | ||
{ | ||
ContainModuleInterface* containModule = container->getContain(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we simplify this code here by creating a Object::getEnclosingContain()
? which only returns ContainModuleInterface*
if it is enclosing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you moved the whole loop into new function. What I meant was:
ContainModuleInterface* Object::getEnclosingContain(Object* containee)
{
ContainModuleInterface* containModule = getContain();
if (containModule && containModule->isEnclosingContainerFor(containee))
{
return containModule;
}
return NULL;
}
This way it is more in line with what getContain
is doing.
And then can loop like so:
Object* Object::getFirstEnclosingContainedBy()
{
for (Object* child = this, Object *container = getContainedBy(); container; child = container, container = container->getContainedBy())
{
if (container->getEnclosingContain(child))
return container;
}
return NULL;
}
Basically keep
getEnclosingContain
in line with getContain
getFirstEnclosingContainedBy
in line with getContainedBy
I did not test it. Just draft.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the current approach unsatisfactory?
Basically keep
getEnclosingContain
in line withgetContain
getFirstEnclosingContainedBy
in line withgetContainedBy
Functionally, getEnclosingContain
is more in line with getContainedBy
as both functions look up the containment chain for an external container object, whereas getContain
is an instance accessor akin to getAI
, getPhysics
, getStealth
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a bit confusing because the original getContain
returns the direct contain module of the object, whereas your proposed getEnclosingContain
returns Null or the first parent contain module that is enclosing. Perhaps name this differently to more clearly conceptually distinguish from getContain
?
Other than that, my proposed getFirstEnclosingContainedBy
allows to get hands on the Object first, which could be useful for future uses, because ContainModuleInterface
currently does not expose the owning object. There simply is much more we can do with an Object
than just ContainModuleInterface
, which makes this function much more versatile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I now understand your thinking behind getEnclosingContain
, from natural language we can assume that it is a parent contain. My monkey brain thinks more of a "get the enclosing contain module that is owned by this object".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my function would be clear with this name:
ContainModuleInterface* Object::getContainIfEnclosing(Object* containee)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a bit confusing because the original
getContain
returns the direct contain module of the object, whereas your proposedgetEnclosingContain
returns Null or the first parent contain module that is enclosing. Perhaps name this differently to more clearly conceptually distinguish fromgetContain
?
It was meant to be comparable to getContainedBy
rather than getContain
, but I see how the naming can be misleading.
How about changing the return type to Object*
and the name to getEnclosingContainedBy
to better align with getContainedBy
?
- ContainModuleInterface* getEnclosingContain();
+ Object* getEnclosingContainedBy();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I suggest implement it roughly the way I suggested above. Can optimize the names where applicable.
This change fixes an issue where propaganda effects persist for contained units that have a direct
PropagandaTowerBehavior
module (e.g. Attack Outpost, Assault Troop Crawler).The contained tower logic was only ever anticipated to be used for the Overlord's tower attachment, which is technically considered as a 'contained' passenger by the Overlord - hence the need for the two container checks. However, as the
PropagandaTowerBehavior
module can be added directly to units themselves, the container check does not function correctly for singular containers.In the 1.04 example below, an Assault Troop Crawler enters a tunnel and its propaganda effect persists for units around the tunnel: