diff --git a/Tactical/Faces.cpp b/Tactical/Faces.cpp index 33ca61ac..f1c8c658 100644 --- a/Tactical/Faces.cpp +++ b/Tactical/Faces.cpp @@ -2184,7 +2184,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE } // Flugente: drag stuff - if (MercPtrs[pFace->ubSoldierID]->IsDraggingSomeone()) + if (MercPtrs[pFace->ubSoldierID]->IsDragging()) { DoRightIcon(uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 31); ++bNumRightIcons; diff --git a/Tactical/Interface Control.cpp b/Tactical/Interface Control.cpp index efb0cb10..0960bd08 100644 --- a/Tactical/Interface Control.cpp +++ b/Tactical/Interface Control.cpp @@ -689,12 +689,12 @@ void DrawExplosionWarning( INT32 sGridno, INT8 sLevel, INT8 sDelay ) // Flugente: draw a circle around a gridno // For now, we aren't using usColour, but that will likely change in the future -void DrawTraitRadius( INT32 sGridno, INT8 sLevel, INT32 sRadius, INT16 sThickness, UINT16 usColour ) +void DrawTraitRadius(INT32 sGridno, INT8 sLevel, INT32 sRadius, INT16 sThickness, UINT16 usColour) { - if ( TileIsOutOfBounds( sGridno ) ) + if (TileIsOutOfBounds(sGridno)) return; - if ( sRadius <= 0 ) + if (sRadius <= 0) return; UINT32 uiDestPitchBYTES; @@ -703,52 +703,50 @@ void DrawTraitRadius( INT32 sGridno, INT8 sLevel, INT32 sRadius, INT16 sThicknes INT16 sScreenX, sScreenY; // Get screen pos of gridno...... - GetGridNoScreenXY( sGridno, &sScreenX, &sScreenY ); + GetGridNoScreenXY(sGridno, &sScreenX, &sScreenY); - // ATE: If we are on a higher interface level, substract.... - if ( sLevel == 1 ) + // ATE: If we are on a higher interface level, subtract.... + if (sLevel == 1) sScreenY -= 50; - - pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES ); + + pDestBuf = LockVideoSurface(FRAME_BUFFER, &uiDestPitchBYTES); // make sure to check for these boundaries later on, and only draw inside them - SetClippingRegionAndImageWidth( uiDestPitchBYTES, gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y ); - + SetClippingRegionAndImageWidth(uiDestPitchBYTES, gsVIEWPORT_START_X, gsVIEWPORT_WINDOW_START_Y, gsVIEWPORT_END_X, gsVIEWPORT_WINDOW_END_Y); + // we determine the biggest rectangle we have to reserve INT32 best_xl = 99999; INT32 best_xr = 0; INT32 best_yl = 99999; INT32 best_yr = 0; BOOLEAN sthdrawn = FALSE; - + INT16 radius_inner = sRadius - sThickness / 2; INT16 radius_outer = sRadius + sThickness / 2; - + // determine area of where the circle will be drawn in, take into account what part of the sector we actually see - INT32 xl = max( gsVIEWPORT_START_X, sScreenX - radius_outer ); - INT32 xr = min( gsVIEWPORT_END_X, sScreenX + radius_outer ); - INT32 yl = max( gsVIEWPORT_WINDOW_START_Y, sScreenY - radius_outer ); - INT32 yr = min( gsVIEWPORT_WINDOW_END_Y, sScreenY + radius_outer ); + INT32 xl = max(gsVIEWPORT_START_X, sScreenX - radius_outer); + INT32 xr = min(gsVIEWPORT_END_X, sScreenX + radius_outer); + INT32 yl = max(gsVIEWPORT_WINDOW_START_Y, sScreenY - radius_outer); + INT32 yr = min(gsVIEWPORT_WINDOW_END_Y, sScreenY + radius_outer); - best_xl = min( best_xl, xl ); - best_xr = max( best_xr, xr ); - best_yl = min( best_yl, yl ); - best_yr = max( best_yr, yr ); + best_xl = min(best_xl, xl); + best_xr = max(best_xr, xr); + best_yl = min(best_yl, yl); + best_yr = max(best_yr, yr); - UINT16 blue = Get16BPPColor( FROMRGB( 0, 0, 255 ) ); - - for ( INT32 x = xl; x <= xr; ++x ) + for (INT32 x = xl; x <= xr; ++x) { FLOAT xdiffsquared = (FLOAT)((sScreenX - x) * (sScreenX - x)); - for ( INT32 y = yl; y <= yr; ++y ) + for (INT32 y = yl; y <= yr; ++y) { - FLOAT diff = sqrt( (FLOAT)(xdiffsquared + 4 * (sScreenY - y) * (sScreenY - y)) ); + FLOAT diff = sqrt((FLOAT)(xdiffsquared + 4 * (sScreenY - y) * (sScreenY - y))); - if ( radius_inner <= diff && diff <= radius_outer ) + if (radius_inner <= diff && diff <= radius_outer) { // we alter the colour of existing pixels instead of fully replacing the colour. As a result, one can still see the map regions we draw over, which looks a lot better - PixelAlterColour( FALSE, x, y, blue, pDestBuf ); + PixelAlterColour(FALSE, x, y, usColour, pDestBuf); sthdrawn = TRUE; } @@ -771,7 +769,7 @@ void DrawTraitRadius( INT32 sGridno, INT8 sLevel, INT32 sRadius, INT16 sThicknes } } - UnLockVideoSurface( FRAME_BUFFER ); + UnLockVideoSurface(FRAME_BUFFER); } void RenderTopmostTacticalInterface( ) diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 40f165f6..8ddaaf69 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3241,7 +3241,7 @@ UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier, BOOLEAN fConsiderDragging UINT32 uiTotalWeight = GetTotalWeight( pSoldier ); // Flugente: if we drag someone, add their weight to ours - if ( fConsiderDragging && pSoldier->IsDraggingSomeone() ) + if ( fConsiderDragging && pSoldier->IsDragging() ) { if (pSoldier->usDragPersonID != NOBODY) { diff --git a/Tactical/PATHAI.cpp b/Tactical/PATHAI.cpp index 4c00a2b7..85abdf3f 100644 --- a/Tactical/PATHAI.cpp +++ b/Tactical/PATHAI.cpp @@ -3667,7 +3667,7 @@ if(!GridNoOnVisibleWorldTile(iDestination)) } // Flugente: dragging someone - if ( s->IsDraggingSomeone( ) ) + if ( s->IsDragging( ) ) { ubAPCost *= gItemSettings.fDragAPCostModifier; } @@ -4782,7 +4782,7 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl } // Flugente: dragging someone - if ( pSold->IsDraggingSomeone( ) ) + if ( pSold->IsDragging( ) ) { sMovementAPsCost *= gItemSettings.fDragAPCostModifier; } @@ -4922,7 +4922,7 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl } // Flugente: dragging someone - if ( pSold->IsDraggingSomeone() ) + if ( pSold->IsDragging() ) { sPointsWalk *= gItemSettings.fDragAPCostModifier; sPointsCrawl *= gItemSettings.fDragAPCostModifier; diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index a19c7865..0ca8302b 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -562,7 +562,7 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, UINT16 u sPoints *= gItemSettings.fShieldMovementAPCostModifier; // Flugente: dragging someone - if ( pSoldier->IsDraggingSomeone( ) ) + if ( pSoldier->IsDragging( ) ) sPoints *= gItemSettings.fDragAPCostModifier; // Flugente: scuba fins reduce movement cost in water, but increase cost on land @@ -4299,7 +4299,7 @@ INT16 GetAPsStartRun( SOLDIERTYPE *pSoldier ) if ( pSoldier->IsRiotShieldEquipped( ) ) val *= gItemSettings.fShieldMovementAPCostModifier; - if ( pSoldier->IsDraggingSomeone( ) ) + if ( pSoldier->IsDragging( ) ) val *= gItemSettings.fDragAPCostModifier; // Athletics trait @@ -4667,3 +4667,19 @@ INT16 GetAPsToBreakWindow(SOLDIERTYPE *pSoldier, BOOLEAN fStance) return MinAPsToPunch(pSoldier, NOWHERE); } + +INT16 GetAPsToStartDrag(SOLDIERTYPE *pSoldier, BOOLEAN fStance) +{ + INT16 sAPCost = 0; + + if (fStance && gAnimControl[pSoldier->usAnimState].ubEndHeight != ANIM_CROUCH) + { + if (gAnimControl[pSoldier->usAnimState].ubEndHeight > ANIM_CROUCH) + sAPCost += GetAPsCrouch(pSoldier, TRUE); + else + sAPCost += GetAPsProne(pSoldier, TRUE); + } + + return sAPCost; +} + diff --git a/Tactical/Points.h b/Tactical/Points.h index f9b6d82c..7ca66c9d 100644 --- a/Tactical/Points.h +++ b/Tactical/Points.h @@ -389,5 +389,6 @@ INT32 GetBPCostForRecoilkick( SOLDIERTYPE * pSoldier ); // sevenfm INT16 GetAPsToBreakWindow(SOLDIERTYPE *pSoldier, BOOLEAN fStance); +INT16 GetAPsToStartDrag(SOLDIERTYPE *pSoldier, BOOLEAN fStance); #endif diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 908bcc8c..acad2141 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -9332,7 +9332,7 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier } // Flugente: drag people - if ( pSoldier->IsDraggingSomeone( false ) ) + if ( pSoldier->IsDragging( false ) ) { pSoldier->sAniDelay = gItemSettings.fDragAPCostModifier * pSoldier->sAniDelay; } @@ -11775,7 +11775,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR // Flugente: as we move a tile, we would now be too far away to drag someone. // So remember whether we were dragging (we have to set our position now, otherwise the person we drag woul soon occupy our gridno). - BOOLEAN currentlydragging = this->IsDraggingSomeone(); + BOOLEAN currentlydragging = this->IsDragging(); INT32 sOldGridNo = this->sGridNo; // OK, set new position @@ -18322,7 +18322,8 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo ) case SKILLS_DRAG: // TODO: a better check would be whether we can drag anything at the moment - CanDrag is more used for a specific person - if ( CanDragInPrinciple() ) + // sevenfm: added AP check to crouch before starting to drag + if ((!fAPCheck || EnoughPoints(this, GetAPsToStartDrag(this, sGridNo), 0, FALSE)) && CanDragInPrinciple()) canuse = TRUE; break; @@ -18467,6 +18468,11 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID ) break; case SKILLS_DRAG: + // sevenfm: change to crouch before dragging + if (gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH) + { + HandleStanceChangeFromUIKeys(ANIM_CROUCH); + } if ( usMapPos != NOWHERE ) SetDragOrderStructure( usMapPos ); else if ( ID < NOBODY ) @@ -18650,8 +18656,9 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill, INT32 sGridNo ) swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_PRONEPERSONORCORPSE] ); wcscat( skilldescarray, atStr ); - swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_CROUCH] ); - wcscat( skilldescarray, atStr ); + // sevenfm: allow to start dragging from any stance, will crouch automatically + //swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_CROUCH] ); + //wcscat( skilldescarray, atStr ); swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_FREEHANDS] ); wcscat( skilldescarray, atStr ); @@ -20736,10 +20743,10 @@ void SOLDIERTYPE::RiotShieldTakeDamage( INT32 sDamage ) } // Flugente: drag people -BOOLEAN SOLDIERTYPE::CanDragInPrinciple() +BOOLEAN SOLDIERTYPE::CanDragInPrinciple(BOOLEAN fCheckStance) { - // only prone while crouched - if ( gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH ) + // only allow while crouched + if (fCheckStance && gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH) return FALSE; // not in water @@ -20753,9 +20760,9 @@ BOOLEAN SOLDIERTYPE::CanDragInPrinciple() return TRUE; } -BOOLEAN SOLDIERTYPE::CanDragPerson( UINT16 usID ) +BOOLEAN SOLDIERTYPE::CanDragPerson(UINT16 usID, BOOLEAN fCheckStance) { - if ( !CanDragInPrinciple() ) + if (!CanDragInPrinciple(fCheckStance)) return FALSE; // check whether this guy exists etc. @@ -20794,9 +20801,9 @@ BOOLEAN SOLDIERTYPE::CanDragPerson( UINT16 usID ) return FALSE; } -BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum ) +BOOLEAN SOLDIERTYPE::CanDragCorpse(UINT16 usCorpseNum, BOOLEAN fCheckStance) { - if ( !CanDragInPrinciple( ) ) + if (!CanDragInPrinciple(fCheckStance)) return FALSE; ROTTING_CORPSE* pCorpse = GetRottingCorpse( usCorpseNum ); @@ -20826,9 +20833,9 @@ BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum ) return FALSE; } -BOOLEAN SOLDIERTYPE::CanDragStructure( INT32 sGridNo ) +BOOLEAN SOLDIERTYPE::CanDragStructure(INT32 sGridNo, BOOLEAN fCheckStance) { - if ( !CanDragInPrinciple() ) + if (!CanDragInPrinciple(fCheckStance)) return FALSE; if ( sGridNo == NOWHERE ) @@ -21013,27 +21020,27 @@ BOOLEAN SOLDIERTYPE::CanDragStructure( INT32 sGridNo ) return TRUE; } -BOOLEAN SOLDIERTYPE::IsDraggingSomeone( bool aStopIfConditionNotSatisfied ) +BOOLEAN SOLDIERTYPE::IsDragging( bool aStopIfConditionNotSatisfied ) { - if ( this->sDragCorpseID >= 0 ) + if (this->sDragCorpseID >= 0) { - if ( this->CanDragCorpse(this->sDragCorpseID) ) + if (this->CanDragCorpse(this->sDragCorpseID, TRUE)) return TRUE; - else if ( aStopIfConditionNotSatisfied ) + else if (aStopIfConditionNotSatisfied) CancelDrag(); } - else if ( this->usDragPersonID != NOBODY ) + else if (this->usDragPersonID != NOBODY) { - if ( this->CanDragPerson(this->usDragPersonID) ) + if (this->CanDragPerson(this->usDragPersonID, TRUE)) return TRUE; - else if ( aStopIfConditionNotSatisfied ) + else if (aStopIfConditionNotSatisfied) CancelDrag(); } - else if ( this->sDragGridNo != NOWHERE ) + else if (this->sDragGridNo != NOWHERE) { - if ( this->CanDragStructure( this->sDragGridNo ) ) + if (this->CanDragStructure(this->sDragGridNo, TRUE)) return TRUE; - else if ( aStopIfConditionNotSatisfied ) + else if (aStopIfConditionNotSatisfied) CancelDrag(); } @@ -21105,6 +21112,12 @@ void SOLDIERTYPE::SetDragOrderStructure( INT32 sGridNo ) void SOLDIERTYPE::CancelDrag() { + // sevenfm: update face icon + if (this->usDragPersonID != NOBODY || this->sDragCorpseID != -1 || this->sDragGridNo != NOWHERE) + { + fInterfacePanelDirty = DIRTYLEVEL2; + } + // if we are dragging a person, set them to the center of their gridno, otherwise their position might be off if (this->usDragPersonID != NOBODY) { @@ -24454,6 +24467,130 @@ BOOLEAN SOLDIERTYPE::CanBreakWindow(void) return FALSE; } +BOOLEAN SOLDIERTYPE::CanStartDrag(void) +{ + if (!this->IsDragging(false) && this->CanDragInPrinciple()) + { + INT32 sNewGridNo = NewGridNo(this->sGridNo, DirectionInc(this->ubDirection)); + + if (!TileIsOutOfBounds(sNewGridNo) && sNewGridNo != this->sGridNo) + { + // soldiers + for (UINT32 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; cnt <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++cnt) + { + if (cnt != this->ubID && + MercPtrs[cnt] && + MercPtrs[cnt]->sGridNo == sNewGridNo && + this->CanDragPerson(cnt)) + { + return TRUE; + } + } + + // corpses + ROTTING_CORPSE* pCorpse; + for (INT32 cnt = 0; cnt < giNumRottingCorpse; ++cnt) + { + pCorpse = &(gRottingCorpse[cnt]); + + if (pCorpse && + pCorpse->fActivated && + pCorpse->def.bLevel == this->pathing.bLevel && + sNewGridNo == pCorpse->def.sGridNo && + this->CanDragCorpse(pCorpse->iID)) + { + return TRUE; + } + } + + // gridno + UINT32 tiletype; + UINT16 structurenumber; + UINT8 hitpoints; + UINT8 decalflag; + + if (this->CanDragStructure(sNewGridNo) && + IsDragStructurePresent(sNewGridNo, this->pathing.bLevel, tiletype, structurenumber, hitpoints, decalflag)) + { + int xmlentry; + GetDragStructureXmlEntry(tiletype, structurenumber, xmlentry); + + if (xmlentry >= 0) + { + return TRUE; + } + } + } + } + + return FALSE; +} + +void SOLDIERTYPE::StartDrag(void) +{ + if (this->CanDragInPrinciple()) + { + if (gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH) + { + HandleStanceChangeFromUIKeys(ANIM_CROUCH); + } + + INT32 sNewGridNo = NewGridNo(this->sGridNo, DirectionInc(this->ubDirection)); + + if (!TileIsOutOfBounds(sNewGridNo) && sNewGridNo != this->sGridNo) + { + // soldiers + for (UINT32 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; cnt <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++cnt) + { + if (cnt != this->ubID && + MercPtrs[cnt] && + MercPtrs[cnt]->sGridNo == sNewGridNo && + this->CanDragPerson(cnt)) + { + SetDragOrderPerson(cnt); + fInterfacePanelDirty = DIRTYLEVEL2; + } + } + + // corpses + ROTTING_CORPSE* pCorpse; + for (INT32 cnt = 0; cnt < giNumRottingCorpse; ++cnt) + { + pCorpse = &(gRottingCorpse[cnt]); + + if (pCorpse && + pCorpse->fActivated && + pCorpse->def.bLevel == this->pathing.bLevel && + sNewGridNo == pCorpse->def.sGridNo && + this->CanDragCorpse(pCorpse->iID)) + { + SetDragOrderCorpse(pCorpse->iID); + fInterfacePanelDirty = DIRTYLEVEL2; + } + } + + // gridno + UINT32 tiletype; + UINT16 structurenumber; + UINT8 hitpoints; + UINT8 decalflag; + + if (this->CanDragStructure(sNewGridNo) && + IsDragStructurePresent(sNewGridNo, this->pathing.bLevel, tiletype, structurenumber, hitpoints, decalflag)) + { + int xmlentry; + GetDragStructureXmlEntry(tiletype, structurenumber, xmlentry); + + if (xmlentry >= 0) + { + SetDragOrderStructure(sNewGridNo); + fInterfacePanelDirty = DIRTYLEVEL2; + } + } + } + } +} + BOOLEAN DoesSoldierWearGasMask( SOLDIERTYPE *pSoldier )//dnl ch40 200909 { INT8 bPosOfMask = FindGasMask( pSoldier ); diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 4615828c..eff711d0 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1792,6 +1792,8 @@ public: // sevenfm void BreakWindow(void); BOOLEAN CanBreakWindow(void); + BOOLEAN CanStartDrag(void); + void StartDrag(void); void UpdateRobotControllerGivenController( void ); void UpdateRobotControllerGivenRobot( void ); @@ -2049,11 +2051,11 @@ public: void RiotShieldTakeDamage(INT32 sDamage); // Flugente: drag people - BOOLEAN CanDragInPrinciple(); - BOOLEAN CanDragPerson( UINT16 usID ); - BOOLEAN CanDragCorpse( UINT16 usCorpseNum ); - BOOLEAN CanDragStructure( INT32 sGridNo ); - BOOLEAN IsDraggingSomeone(bool aStopIfConditionNotSatisfied = true); + BOOLEAN CanDragInPrinciple(BOOLEAN fCheckStance = FALSE); + BOOLEAN CanDragPerson(UINT16 usID, BOOLEAN fCheckStance = FALSE); + BOOLEAN CanDragCorpse(UINT16 usCorpseNum, BOOLEAN fCheckStance = FALSE); + BOOLEAN CanDragStructure(INT32 sGridNo, BOOLEAN fCheckStance = FALSE); + BOOLEAN IsDragging(bool aStopIfConditionNotSatisfied = true); void SetDragOrderPerson( UINT16 usID ); void SetDragOrderCorpse( UINT32 usID ); void SetDragOrderStructure( INT32 sGridNo ); diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index af0f75aa..603f7b1e 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -2246,7 +2246,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) // sevenfm: also stop dragging if (gusSelectedSoldier != NOBODY && MercPtrs[gusSelectedSoldier] && - MercPtrs[gusSelectedSoldier]->IsDraggingSomeone(false)) + MercPtrs[gusSelectedSoldier]->IsDragging(false)) { MercPtrs[gusSelectedSoldier]->CancelDrag(); DirtyMercPanelInterface(MercPtrs[gusSelectedSoldier], DIRTYLEVEL2); @@ -2965,10 +2965,21 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) SOLDIERTYPE *pSoldier; if (GetSoldier(&pSoldier, gusSelectedSoldier)) { - if (pSoldier->CanBreakWindow() && EnoughPoints(pSoldier, GetAPsToBreakWindow(pSoldier, TRUE), BP_USE_CROWBAR, TRUE)) - pSoldier->BreakWindow(); - //else if (pSoldier->CanStartDrag()) - //pSoldier->StartDrag(); + if (pSoldier->CanBreakWindow()) + { + if (EnoughPoints(pSoldier, GetAPsToBreakWindow(pSoldier, TRUE), BP_USE_CROWBAR, TRUE)) + pSoldier->BreakWindow(); + } + else if (pSoldier->CanStartDrag()) + { + INT32 sNewGridNo = NewGridNo(pSoldier->sGridNo, DirectionInc(pSoldier->ubDirection)); + + if (!TileIsOutOfBounds(sNewGridNo) && sNewGridNo != pSoldier->sGridNo) + { + if (EnoughPoints(pSoldier, GetAPsToStartDrag(pSoldier, sNewGridNo), 0, TRUE)) + pSoldier->StartDrag(); + } + } } } break; diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index 0de38d10..8f6db0d0 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -5504,7 +5504,7 @@ UINT8 MovementNoise(SOLDIERTYPE *pSoldier) } // sevenfm: if dragging something, add dragging sound volume - if(pSoldier->IsDraggingSomeone()) + if(pSoldier->IsDragging()) { sVolume = max(sVolume, MAX_MOVEMENT_NOISE / 2 + Random(MAX_MOVEMENT_NOISE) + bGroundVolumeModifier); } diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 52493f13..b229c575 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -38,6 +38,7 @@ #include "CampaignStats.h" // added by Flugente #include "Points.h" // added by Flugente #include "Interface Control.h" // added by Flugente for DrawExplosionWarning(...) +#include "SkillMenu.h" #endif #include "Soldier Macros.h" @@ -4327,6 +4328,8 @@ void HandleExplosionQueue( void ) } } +extern DragSelection gDragSelection; + // Flugente: show warnings around armed timebombs both in map and inventories void HandleExplosionWarningAnimations( ) { @@ -4379,28 +4382,123 @@ void HandleExplosionWarningAnimations( ) } } + UINT16 usBlue = Get16BPPColor(FROMRGB(0, 0, 255)); + UINT16 usColor; + INT32 sRadius; + // show focus area if skill is active if ( gusSelectedSoldier != NOBODY ) { SOLDIERTYPE* pSoldier = MercPtrs[gusSelectedSoldier]; - if ( pSoldier->bActive && pSoldier->bInSector && (pSoldier->usSoldierFlagMask2 & SOLDIER_TRAIT_FOCUS) ) + if ( pSoldier->bActive && pSoldier->bInSector) { - // checking whether this skill is active is relatively cheap. If it fails, deactivate skill properly - // we cannot use CanUseSkill(...) again though, as this would fail upon opening the menu - if ( pSoldier->CanUseSkill( SKILLS_FOCUS, FALSE, pSoldier->sFocusGridNo ) ) + if (pSoldier->usSoldierFlagMask2 & SOLDIER_TRAIT_FOCUS) { - // radius depends on range - INT16 range = PythSpacesAway(pSoldier->sFocusGridNo, pSoldier->sGridNo); - INT16 radius = gSkillTraitValues.ubSNFocusRadius * range / 20; + // checking whether this skill is active is relatively cheap. If it fails, deactivate skill properly + // we cannot use CanUseSkill(...) again though, as this would fail upon opening the menu + if (pSoldier->CanUseSkill(SKILLS_FOCUS, FALSE, pSoldier->sFocusGridNo)) + { + // radius depends on range + INT16 range = PythSpacesAway(pSoldier->sFocusGridNo, pSoldier->sGridNo); + INT16 radius = gSkillTraitValues.ubSNFocusRadius * range / 20; - DrawTraitRadius( pSoldier->sFocusGridNo, pSoldier->pathing.bLevel, sqrt( 0.5 ) * (20 + 40 * radius), 8, 0 ); + DrawTraitRadius(pSoldier->sFocusGridNo, pSoldier->pathing.bLevel, sqrt(0.5) * (20 + 40 * radius), 8, usBlue); + } + else + { + // if conditions don't apply, deactivate skill. This will cause it to update to status changes very fast + pSoldier->usSoldierFlagMask2 &= ~SOLDIER_TRAIT_FOCUS; + pSoldier->sFocusGridNo = NOWHERE; + } } - else + + // sevenfm: show draggable objects + if (gDragSelection.Active()) // || gCurrentUIMode == HANDCURSOR_MODE) { - // if conditions don't apply, deactivate skill. This will cause it to update to status changes very fast - pSoldier->usSoldierFlagMask2 &= ~SOLDIER_TRAIT_FOCUS; - pSoldier->sFocusGridNo = NOWHERE; + // check all tiles on screen + UINT32 tiletype; + UINT16 structurenumber; + UINT8 hitpoints; + UINT8 decalflag; + INT8 bLevel = pSoldier->pathing.bLevel; + UINT16 usRoomNo; + + for (INT32 sSpot = 0; sSpot < WORLD_MAX; sSpot++) + { + if (!TileIsOutOfBounds(sSpot) && + GridNoOnVisibleWorldTile(sSpot) && + GridNoOnScreen(sSpot) && + !TERRAIN_IS_HIGH_WATER(sSpot) && + !InAHiddenRoom(sSpot, &usRoomNo)) + { + BOOLEAN fShow = FALSE; + + if (IsDragStructurePresent(sSpot, bLevel, tiletype, structurenumber, hitpoints, decalflag) && + !Water(sSpot, bLevel) && + FindNotWaterNearby(sSpot, bLevel)) + { + fShow = TRUE; + } + + // soldiers + if (!fShow) + { + for (UINT32 ubID = gTacticalStatus.Team[OUR_TEAM].bFirstID; ubID <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++ubID) + { + if (ubID != pSoldier->ubID && + MercPtrs[ubID] && + MercPtrs[ubID]->sGridNo == sSpot && + MercPtrs[ubID]->bVisible == TRUE && + MercPtrs[ubID]->pathing.bLevel == bLevel && + gAnimControl[MercPtrs[ubID]->usAnimState].ubEndHeight == ANIM_PRONE && + !Water(MercPtrs[ubID]->sGridNo, MercPtrs[ubID]->pathing.bLevel) && + pSoldier->ubBodyType <= REGFEMALE && + (MercPtrs[ubID]->bTeam == pSoldier->bTeam || MercPtrs[ubID]->IsUnconscious() || MercPtrs[ubID]->stats.bLife < OKLIFE)) + { + fShow = TRUE; + } + } + } + + // corpses + if (!fShow) + { + ROTTING_CORPSE* pCorpse; + for (INT32 sCorpseID = 0; sCorpseID < giNumRottingCorpse; ++sCorpseID) + { + pCorpse = &(gRottingCorpse[sCorpseID]); + + if (pCorpse && + pCorpse->fActivated && + pCorpse->def.bLevel == pSoldier->pathing.bLevel && + pCorpse->def.bVisible == TRUE && + sSpot == pCorpse->def.sGridNo && + pCorpse->def.ubBodyType < COW && + pCorpse->def.ubBodyType != QUEENMONSTER) + { + fShow = TRUE; + } + } + } + + if (fShow) + { + usColor = Get16BPPColor(FROMRGB(64, 0, 96)); + sRadius = (INT32)(sqrt(0.5) * (20)); + + if (bLevel > 0) + { + DrawTraitRadius(sSpot, bLevel, sRadius, 2, usColor); + DrawTraitRadius(sSpot, bLevel, sRadius + 4, 2, usColor); + } + else + { + DrawTraitRadius(sSpot, bLevel, sRadius, 2, usColor); + } + } + } + } } } }