|
23 | 23 | //////////////////////////////////////////////////////////////////////////////// |
24 | 24 |
|
25 | 25 | #include "PreRTS.h" |
26 | | -#include "GameClient/SelectionInfo.h" |
27 | 26 |
|
28 | | -#include "Common/ActionManager.h" |
29 | 27 | #include "GameLogic/Damage.h" |
30 | | -#include "Common/Player.h" |
31 | | -#include "Common/PlayerList.h" |
| 28 | +#include "GameLogic/Module/ContainModule.h" |
| 29 | + |
| 30 | +#include "Common/ActionManager.h" |
32 | 31 | #include "Common/ThingTemplate.h" |
| 32 | +#include "Common/PlayerList.h" |
| 33 | +#include "Common/Player.h" |
33 | 34 |
|
| 35 | +#include "GameClient/SelectionInfo.h" |
34 | 36 | #include "GameClient/CommandXlat.h" |
35 | 37 | #include "GameClient/ControlBar.h" |
36 | 38 | #include "GameClient/Drawable.h" |
@@ -61,9 +63,8 @@ SelectionInfo::SelectionInfo() : |
61 | 63 | { } |
62 | 64 |
|
63 | 65 | //------------------------------------------------------------------------------------------------- |
64 | | -PickDrawableStruct::PickDrawableStruct() : drawableListToFill(nullptr) |
| 66 | +PickDrawableStruct::PickDrawableStruct() : drawableListToFill(nullptr), isPointSelection(FALSE) |
65 | 67 | { |
66 | | - drawableListToFill = FALSE; |
67 | 68 | forceAttackMode = TheInGameUI->isInForceAttackMode(); |
68 | 69 | UnsignedInt pickType = getPickTypesForContext(forceAttackMode); |
69 | 70 | translatePickTypesToKindof(pickType, kindofsToMatch); |
@@ -360,7 +361,36 @@ Bool addDrawableToList( Drawable *draw, void *userData ) |
360 | 361 | return FALSE; |
361 | 362 |
|
362 | 363 | if (!draw->isSelectable()) |
363 | | - return FALSE; |
| 364 | + { |
| 365 | + const Object *obj = draw->getObject(); |
| 366 | + if ( obj && obj->getContainedBy() )//hmm, interesting... he is not selectable but he is contained |
| 367 | + {// What we are after here is to propagate the selection the selection ti the container |
| 368 | + // if the container is non-enclosing... see also SelectionXlat, in the left_click case |
| 369 | + |
| 370 | + ContainModuleInterface *contain = obj->getContainedBy()->getContain(); |
| 371 | + Drawable *containDraw = obj->getContainedBy()->getDrawable(); |
| 372 | + if (contain && ! contain->isEnclosingContainerFor( obj ) && containDraw ) |
| 373 | + return addDrawableToList( containDraw, userData ); |
| 374 | + } |
| 375 | + else |
| 376 | + return FALSE; |
| 377 | + } |
| 378 | + |
| 379 | +#if !RTS_GENERALS && PRESERVE_RETAIL_BEHAVIOR |
| 380 | + // TheSuperHackers @info |
| 381 | + // In retail, hidden objects such as passengers are included here when drag-selected, which causes |
| 382 | + // enemy selection logic to exit early (only 1 enemy unit can be selected at a time). Some players |
| 383 | + // exploit this bug to determine if a transport contains passengers and consider this an important |
| 384 | + // feature and an advanced skill to pull off, so we must leave the exploit. |
| 385 | + if (!pds->isPointSelection) |
| 386 | + { |
| 387 | + const Object *obj = draw->getObject(); |
| 388 | + if (obj) |
| 389 | + if (obj->getControllingPlayer() != ThePlayerList->getLocalPlayer()) |
| 390 | + if (obj->getContain() && draw->getObject()->getContain()->getContainCount() > 0) |
| 391 | + return FALSE; |
| 392 | + } |
| 393 | +#endif |
364 | 394 |
|
365 | 395 | pds->drawableListToFill->push_back(draw); |
366 | 396 | return TRUE; |
|
0 commit comments